2014-07-28 2 views
0

я пытаюсь скомпилировать простую программустанд :: ifstream ведет себя странно с временным станд :: строка() в качестве аргумента конструктора

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.

ответ

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 потребуется c_str().

Как вы говорите, вы можете просто передать argv[1] в качестве аргумента на любом диалекте C++, полностью избегая досадного разбора.

Смежные вопросы