代码之家  ›  专栏  ›  技术社区  ›  Christopher Bruns

构造函数(C++)中的临时非标准引用

  •  1
  • Christopher Bruns  · 技术社区  · 15 年前

    在C++中,构造一个非istt引用的构造函数似乎不能用临时值构造。

    #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&)
    

    构造条形对象的第二种方法(bar2)在哲学上有什么问题吗?对我来说,它看起来更好,并且不需要只需要片刻的stream1变量。

    编辑 :为了回应Johannes Schaub的评论,我想给出更多的背景。首先,这不是我第一次被C++的行为所困扰,所以我对这个问题的更高层次的哲学讨论感兴趣。也就是说,在这个特殊的例子中,我有一个类,它读取一个包含用于构造对象的数据的文件。我还喜欢编写使用字符串而不是文件的自动测试。但是,将该文件用于构建是主要的用例。所以我决定创建一个采用IStream的构造函数,这样我就可以使用文件(流)或字符串(流)。我就是这样来到这里的。我的测试程序直接从字符串构造对象,以模拟读取文件。这就省去了为每个小测试创建单独数据文件的麻烦。

    2 回复  |  直到 15 年前
        1
  •  3
  •   Roger Pate    15 年前

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

    C++ 0x将有R值引用,并在这里更改一些内容。人们试图对这一问题的两个方面进行各种各样的哲学解释,但我没有找到一种完全令人信服的解释。似乎更多的是“你只需要选择一种行为并坚持它”,这解释了当前的C++和0x的变化:所选择的行为已经发生了变化。

        2
  •  1
  •   Potatoswatter    15 年前

    罗杰是正确的,这是C++的通用策略,只有const引用可以绑定到临时变量。不过,我不认为右值引用可以帮助您,因为在传递非临时流的情况下, 希望继续使用其修改状态。

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