为什么我不能在构建它时传递ifstream?

时间:2013-05-18 04:07:46

标签: c++ ifstream

编译器不喜欢下面的主程序

int get1(ifstream &f){
  int count;
  f >> count;
return count;
}

int main(int argc, char** argv){
  cout << get1(ifstream(argv[1])) << endl;
}

错误消息是:

test.cpp: In function 'int main(int, char**)':
test.cpp:11:33: error: invalid initialization of non-const reference of type 's\
td::ifstream& {aka std::basic_ifstream<char>&}' from an rvalue of type 'std::if\
stream {aka std::basic_ifstream<char>}'
test.cpp:4:5: error: in passing argument 1 of 'int get1(std::ifstream&)'

如果主程序写为

,这确实有效
int main(int argc, char** argv){
  ifstream f(argv[1]);
  cout << get1(f) << endl;
}

有没有办法让紧凑的第一个表单起作用?

1 个答案:

答案 0 :(得分:9)

get1(ifstream(argv[1]))

您正在构建临时 ifstream对象。临时对象只能绑定到const引用(const ifstream&),而不能绑定到非const引用(ifstream&)。

  

有没有办法让紧凑的第一个表单起作用?

这取决于您使用的是哪个版本的C ++。

在C ++ 11 中,您可以将函数更改为使用 rvalue 引用而不是左值引用:int get1(ifstream&& f) 。然后它会很乐意接受临时物品。 (解决方案由@soon提供

但请注意,使用此解决方案时,如果要使用不太紧凑的表单ifstream f(argv[1]); get1(f);,编译器将不会按原样接受它(cannot bind ‘T’ lvalue to ‘T&&’)。您必须使用std::move才能将左值转换为 rvalue get1(std::move(f));

另一种避免std::move要求的方法是使用带有通用引用的模板函数(模板的 rvalue 引用的特殊情况,允许 rvalue 引用衰减到 lvalue 引用):template<Stream> int get1(Stream&& f)礼貌@soon再次

在C ++ 03 中没有标准的方法:由于临时对象只能绑定到const引用,你必须将你的函数改为int get1(const ifstream& f)会让你的ifstream无用(谁想要一个无法读取的ifstream,因为它是const?)。