构造函数中的临时非const istream引用(C ++)

时间:2010-03-09 00:37:27

标签: c++ constructor pass-by-reference

似乎一个对istream采用非const引用的构造函数不能用C ++中的临时值构造。

#include <iostream>
#include <sstream>

using namespace std;

class Bar
{
public:
   explicit Bar(std::istream& is) {}
};

int main()
{
   istringstream stream1("bar1");
   Bar bar1(stream1); // OK on all platforms

   // compile error on linux, Mac gcc; OK on Windows MSVC
   Bar bar2(istringstream("bar2"));

   return 0;
}

这与MSVC编译良好,但不与gcc编译。使用gcc我得到一个编译错误:

g++     test.cpp   -o test
test.cpp: In function ‘int main()’:
test.cpp:18: error: no matching function for call to ‘Bar::Bar(std::istringstream)’
test.cpp:9: note: candidates are: Bar::Bar(std::istream&)
test.cpp:7: note:                 Bar::Bar(const Bar&)

构建Bar对象的第二种方式(bar2)是否存在哲学上的错误?它对我来说看起来更好,并且不需要只需要片刻的stream1变量。

编辑:在回应Johannes Schaub的评论时,我想提供一些更多的背景信息。首先,这不是我第一次被C ++的这种行为所困扰,所以我真的对这个问题的更高层次的哲学讨论感兴趣。也就是说,在这种特殊情况下,我有一个类,它读入包含用于构造对象的数据的文件。我也喜欢编写使用字符串而不是文件的自动化测试。但使用该文件进行构建是主要用例。所以我决定创建一个带有istream的构造函数,所以我可以使用文件(流)或字符串(流)。这就是我到这里的方式。我的测试程序直接从字符串构造对象,以模拟读取文件。这为我节省了为每个小测试创建单独数据文件的麻烦。

2 个答案:

答案 0 :(得分:3)

这就是C ++当前的工作原理:您不能将非const引用绑定到临时对象。 MSVC允许这样做是非标准的。

C ++ 0x将具有r值引用并在此处稍微改变一下。人们试图对这个问题的双方都有各种各样的哲学解释 - 但我没有找到一个完全令人信服的解释。似乎更多的是“你只需选择一种行为并坚持下去”,这解释了当前的C ++和0x的变化:所选行为已经发生了变化。

答案 1 :(得分:1)

Roger是对的...这是C ++的通用策略,只有const引用可以绑定到临时对象。我不认为右值引用会对你有帮助,因为在传递非临时流的情况下你想要继续使用它的修改状态。

更重要的是,为什么不用friend提取器istream &operator>>(istream &s, Bar &b)替换构造函数?以向对象添加未初始化状态为代价,语法将更加C ++ - ish。