2016-04-04 7 views
2

次のクラスの例を、より大きなプロジェクトから簡略化しました。これは、ロガーのスコープを使用してデストラクタ内のログエントリを終了させるロギングフレームワークに基づいています。 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; 
} 

「作業がうまくいく」というラベルが付いています。それは新しいstd::ostringstreamを含む匿名のContainerオブジェクトをインスタンス化するようです。これは直接 "world"を出力するためにアクセスできます。 Container自体がメッセージの「Hello」部分を作成し、そのデストラクタがバッファをフラッシュします。

Containerオブジェクトの名前が付けられて保存されている2番目の部分が正しく動作しないのはなぜですか?ここに私が得るエラーの例があります:

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> 

...など。

+0

をええと、これは[この質問](http://stackoverflow.com/q/3442520/2069064)のデュープではありません。 – Barry

答えて

8

これは正常に動作します:

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

しかし、この:

Container cont = Container(); 

は、コピーコンストラクタを必要とします。 std::ostringstreamはコピーコンストラクタブルではないため、Containerはコピーコンストラクタブルではないため、Container::Container(const Container&)が暗黙的に削除されているため、暗黙のうちにstd::basic_ostringstream<char>::basic_ostringstream(const std::basic_ostringstream<char>&)が削除されているというエラーメッセージが表示されます。

このコピーは除外されていますが、コピー/移動の必要条件は、コピー/移動が最初に可能でなければならないということです。

+0

パーフェクト。正しい文「Container cont;」はコンテナを作成しますが、コンテナをコピーしません。私のJavaの背景が表示されています! –

+1

...ユーザー提供のデストラクタが暗黙的な移動コンストラクタを抑制するため、コピーコンストラクタを呼び出します。 –

2

バリーが説明したように、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

関連する問題