【问题标题】:Why can I not pass an ifstream as I construct it?为什么我在构造它时不能传递 ifstream?
【发布时间】:2013-05-18 04:07:46
【问题描述】:

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

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;
}

有没有办法使紧凑的第一种形式起作用?

【问题讨论】:

    标签: c++ ifstream


    【解决方案1】:
    get1(ifstream(argv[1]))
    

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

    有没有办法使紧凑的第一种形式起作用?

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

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

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

    另一种避免std::move 要求的方法是使用带有通用引用的模板函数(模板的右值引用的特殊情况,它允许rvalue 引用衰减为 lvalue 引用):template&lt;Stream&gt; int get1(Stream&amp;&amp; f)再次感谢@soon

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

    【讨论】:

    • 虽然我很不愿意提,因为它绝对烂,有一个办法:MSVC的邪恶扩展。
    • @chris 是的,我犹豫了一下,但最终决定反对:称我为迂腐,但这不再是 C++。
    • 我不确定,但是通过 r-reference 传递不是解决方案吗?
    • @soon:啊对,我没想到。需要时间来提高对 C++11 的反应能力,我是一个学习缓慢的人。谢谢,我会更新我的答案。 :)
    • @syam,或者使用通用参考。(template &lt;class Srteam&gt; int get1(Stream&amp;&amp; s) { ... })
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-10
    • 2019-02-23
    • 1970-01-01
    相关资源
    最近更新 更多