简体   繁体   English

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

[英]Temporary non-const istream reference in constructor (C++)

It seems that a constructor that takes a non-const reference to an istream cannot be constructed with a temporary value in C++. 似乎一个对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;
}

This compiles fine with MSVC, but not with gcc. 这与MSVC编译良好,但不与gcc编译。 Using gcc I get a compile error: 使用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&)

Is there something philosophically wrong with the second way (bar2) of constructing a Bar object? 构造Bar对象的第二种方式(bar2)是否存在哲学上的错误? It looks nicer to me, and does not require that stream1 variable that is only needed for a moment. 它对我来说看起来更好,并且不需要只需要片刻的stream1变量。

EDIT : In response to Johannes Schaub's comment I'd like to give a bit more context. 编辑 :回应约翰内斯绍布的评论,我想提供更多的背景。 First, this is not the first time I have been annoyed by this behavior of C++, so I am genuinely interested in the higher level philosophical discussion of this issue. 首先,这不是我第一次被C ++的这种行为所困扰,所以我真的对这个问题的更高层次的哲学讨论感兴趣。 That said, in this particular case I have a class that reads in a file that contains data used to construct the object. 也就是说,在这种特殊情况下,我有一个类,它读入包含用于构造对象的数据的文件。 I also like to write automated tests that use a string instead of the file. 我也喜欢编写使用字符串而不是文件的自动化测试。 But using the file for construction is the primary use case. 但使用该文件进行构建是主要用例。 So I decided to make a constructor that takes an istream, so I could use either a file(stream), or a string(stream). 所以我决定创建一个带有istream的构造函数,所以我可以使用文件(流)或字符串(流)。 That is how I got here. 这就是我到这里的方式。 My test programs construct objects directly from strings, to simulate reading files. 我的测试程序直接从字符串构造对象,以模拟读取文件。 This saves me the trouble of creating separate data files for each little test. 这为我节省了为每个小测试创建单独数据文件的麻烦。

This is just how C++ works currently: you cannot bind non-const references to temporary objects. 这就是C ++当前的工作原理:您不能将非const引用绑定到临时对象。 MSVC is non-standard in allowing this. MSVC允许这样做是非标准的。

C++0x will have r-value references and change things around a bit here. C ++ 0x将具有r值引用并在此处稍微改变一下。 There are various philosophical interpretations people have tried to apply—for both sides of the issue—but I haven't found one that is wholly convincing. 人们试图对这个问题的双方都有各种各样的哲学解释 - 但我没有找到一个完全令人信服的解释。 It seems more of "you just have to pick one behavior and stick to it", which explains both current C++ and 0x's changes: the chosen behavior has shifted. 似乎更多的是“你必须选择一种行为并坚持下去”,这解释了当前的C ++和0x的变化:所选择的行为已经发生了变化。

Roger is right… this is a generic policy of C++ that only const references may bind to temporaries. Roger是对的......这是C ++的通用策略,只有const引用可以绑定到临时对象。 I don't think rvalue references would help you, though, because in the case of passing a non-temporary stream you do want to continue using its modified state. 我不认为右值引用会对您有所帮助,因为在传递非临时流的情况下,您确实希望继续使用其修改状态。

More to the point, why not replace the constructor with a friend extractor istream &operator>>(istream &s, Bar &b) ? 更重要的是,为什么不用friend提取器替换构造函数istream &operator>>(istream &s, Bar &b) At the cost of adding an uninitialized state to the object, the syntax would be even more C++-ish. 以向对象添加未初始化状态为代价,语法将更加C ++ - ish。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM