【问题标题】:Why can't an object containing a ostringstream member be constructed?为什么不能构造包含 ostringstream 成员的对象?
【发布时间】:2016-07-24 09:13:49
【问题描述】:

我有以下类示例,是从一个更大的项目中简化而来的。它基于一个日志框架,该框架使用 logger 的作用域来终止析构函数中的日志条目。

下面的代码将无法编译,因为构造函数是一个隐式删除的函数(edit: not true),这似乎与std::ostringstream 对象有关。我对此感到困惑,因为我认为我应该能够直接构造一个std::ostringstream,这意味着我应该能够直接构造一个Container 对象。

#include <iostream>
#include <sstream>

class Container {
  public:
    std::ostringstream  bufferStream;

  public:
    Container();    // constructor
    ~Container();
};

Container::Container() {
    bufferStream << "Hello ";
}

Container::~Container() {
    std::cout << bufferStream.str() << " [end]" << std::endl;
}

// === Main method ===

int main() {

    Container().bufferStream << "world";   // works fine

    {                                      // causes tons of compiler errors
        Container cont = Container();
        cont.bufferStream << "world!";
    }

    return 0;
}

请注意,标有“工作正常”的行就是这样做的。好像实例化了一个匿名的Container对象,里面包含了一个新的std::ostringstream,可以直接访问输出“world”。 Container 自身创建消息的“Hello”部分,其析构函数刷新缓冲区。

为什么Container 对象被命名和保存的第二部分不能正确运行?这是我得到的错误示例:

error.cpp: In function ‘int main()’:
error.cpp:28:36: error: use of deleted function ‘Container::Container(const Container&)’
         Container cont = Container();
                                    ^
error.cpp:4:7: note: ‘Container::Container(const Container&)’ is implicitly deleted because the default definition would be ill-formed:
 class Container {
       ^
error.cpp:4:7: error: use of deleted function ‘std::basic_ostringstream<char>::basic_ostringstream(const std::basic_ostringstream<char>&)’
In file included from error.cpp:2:0:
/usr/include/c++/4.8/sstream:387:11: note: ‘std::basic_ostringstream<char>::basic_ostringstream(const std::basic_ostringstream<char>&)’ is implicitly deleted because the default definition would be ill-formed:
     class basic_ostringstream : public basic_ostream<_CharT, _Traits>

...等等。

【问题讨论】:

标签: c++ c++11 ostringstream deleted-functions


【解决方案1】:

正如 Barry 所解释的,ostringstream 不是可复制构造的。由于默认的复制构造函数逐个成员地复制构造,因此无法在此处生成。

但是,如果您遵循rule of three,您将创建一个复制构造函数(以及一个复制赋值运算符),doing what is needed 用于字符串流。然后它会工作:

class Container {
    ...
    Container(const Container&); //Copy constructor
};  

Container::Container(const Container &c) {
    bufferStream << c.bufferStream.rdbuf(); 
}

Online demo

【讨论】:

    【解决方案2】:

    这样可以正常工作:

    Container cont;
    cont.bufferStream << "world!";
    

    但是这个:

    Container cont = Container();
    

    涉及复制构造函数。 std::ostringstream 不是可复制构造的,这使得 Container 不可复制构造,因此由于 std::basic_ostringstream&lt;char&gt;::basic_ostringstream(const std::basic_ostringstream&lt;char&gt;&amp;) 被隐式删除而导致 Container::Container(const Container&amp;) 被隐式删除的错误消息。

    请注意,即使此副本会被省略,复制/移动省略的要求是复制/移动必须可以开始。

    【讨论】:

    • 完美。所以正确的语句Container cont; 构造了容器但不复制它。我的 Java 背景显示出来了!
    • ... 它调用复制构造函数,因为用户提供的析构函数抑制了隐式移动构造函数。
    猜你喜欢
    • 1970-01-01
    • 2021-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-22
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    相关资源
    最近更新 更多