Std::ifstream使用临时Std::string()作为构造函数参数时行为怪异
std::ifstream behaves weirdly with temporary std::string() as constructor argument
我试着编译一个简单的程序
int main(int argc, char* argv[]) {
std::ifstream strings(std::string(argv[1]));
std::string line;
while (!strings.eof()) {
strings >> line;
}
}
并得到奇怪的错误:
error: request for member ‘eof’ in ‘strings’, which is of non-class type ‘std::ifstream(std::string*) {aka std::basic_ifstream<char>(std::basic_string<char>*)}’
如果改成
std::ifstream strings(argv[1]);
都能很好地编译。
这里发生了什么?编译器为gcc 4.7和4.9
这有时被称为最令人烦恼的解析: strings
的声明被解释为函数声明,以指针(表示为数组)作为其参数。为了更清楚地说明这一点,我将删除函数声明中冗余的一些括号:
std::ifstream strings(std::string argv[1]);
,根据数组/指针混淆的古老规则,它相当于
std::ifstream strings(std::string * argv);
与错误消息中提到的类型匹配。
从c++ 11开始,你可以使用大括号初始化来解决这个问题:
std::ifstream strings{std::string(argv[1])};
^ ^
在历史方言中,你需要更多的冗长:
std::ifstream strings = std::ifstream(std::string(argv[1]).c_str());
注意,在c++ 11之前,你不能直接将std::string
传递给构造函数,而需要c_str()
来获得C风格的字符串。
正如您所说,您可以简单地将argv[1]
作为任何c++方言的参数传递,从而完全避免了麻烦的解析。
相关文章:
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 初始化具有非默认构造函数的std::数组项的更好方法
- 编译器如何区分std::vector的构造函数
- 为什么std::vector和std::valarray初始化构造函数不同
- std::make_shared和protected/private构造函数
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- 仅包含可移动 std::map 的类的移动构造函数不起作用
- std::ofstream 作为类成员删除复制构造函数?
- std::string 构造函数如何处理固定大小的 char[]?
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 在构造函数中使用可变参数初始化 std::tuple
- 真的没有来自 std::string_view 的 std::string 的显式构造函数吗?
- 为什么 std::memmove 中联合的默认非平凡移动构造函数C++?
- 如何在构造函数参数中初始化"std::set"?
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- 创建一个没有复制构造函数的类的 std::vector 的 std::vector
- 构造函数采用std::string_view与std::string并移动
- C++ - std::构造函数中的矢量初始化
- 关于 std::bitset 构造函数的几个问题?
- 对 std 构造函数的调用是否需要限定