std :: ifstream与临时std :: string()作为构造函数参数表现得很奇怪

时间:2014-07-28 10:40:20

标签: c++

我尝试编译简单程序

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。

1 个答案:

答案 0 :(得分:4)

这有时被称为最烦恼的解析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样式的字符串。

正如你所说,你可以简单地在任何C ++方言中传递argv[1]作为参数,完全避免无理解析。