0

「暗黙的に削除されたコピー コンストラクターの呼び出し」コンパイル エラーの問題を、クラスのメンバーを宣言する際の ostringstream 型の使用に切り分けました。以下の例では、例の Reading クラスのオブジェクトの STL リストが定義されています。push_back が呼び出された時点で、コンパイラはコピー コンストラクターを検索し、コンパイルは失敗します。これは、Readings のコピー コンストラクターが暗黙的に削除されたためと思われます。

ペイロード文字列を参照する 2 行をコメント アウトすると、プログラムがコンパイルされます。

ここで説明されているように、私の問題は ostringstream が参照型である可能性があると考えています:

https://en.cppreference.com/w/cpp/language/copy_constructor 「T には右辺値参照型のデータ メンバーがあります。」コピー コンストラクターが暗黙的に削除される理由の 1 つとして挙げられます。

Q. ostringstream が参照型であり、問​​題を引き起こしているという私の上記の仮定が正しいかどうか、誰でも確認できますか?

私が ostringstream を使用している理由は、この不自然な例では明らかではありません。この文字列を処理する別の方法を見つける必要があるかもしれませんが、ここで機能するアプローチを誰か提案してもらえますか?

// testing a problem where ostringstream causes implicitly deleted copy constructor
//
// using ostringstream in a class definition seems to cause implicit deletion of the copy constructor

#include <iostream>
#include <sstream>
#include <list>
#include <string>

using namespace std;

class Reading {
    public:
        double elevation;
        std::ostringstream payloadString; // using ostringstream here causes implicit deletion of the copy constructor
        double speed;

    // constructors and member functions
        Reading();          // initialisation constructor declaration
    private:
    };

Reading::Reading(): // initialisation constructor definition
        elevation(0.0),
        payloadString("_null_null_"),  // commenting out this line and the previous definition in the class makes the problem go away
        speed(0.0)
        {}

int main()
{

    std::list<Reading> readingsList; // a list of readings

    Reading fakeReading; // just initialises with dummy data

    // this line is what causes the compiler to complain about implicitly deleted copy constructors
    readingsList.push_back(fakeReading);

    return 0;
}
4

2 に答える 2

0

宣言しない場合 、各クラスには暗黙的に宣言されたコピー コンストラクターがありますが、各データ メンバーと継承された型をコピー構築できる場合に限ります。std::ostringstreamにはコピー コンストラクターがないため、コンパイラは のコピー コンストラクターを生成できませんReading

Reading::payloadString意味のある方法で構築する方法を決定できる場合は、自分でコピー コンストラクターを定義できます。たとえば、次のようなことができます。

Reading(Reading const & other) :
    elevation{other.elevation},
    payloadString{other.payloadString.str()},
    speed{other.speed} { }

これは、含まれている文字列値をコピーしますother.payloadStringが、さまざまな出力モードや出力位置など、ストリームの他の側面はコピーしないことに注意してください。あなたのケースではこれで十分かもしれません。

このコンストラクターを定義する場合は、同じ理由で自動的に生成できないコピー代入操作も定義する必要があります。上記のコピー コンストラクターのセマンティクスを模倣できます。

Reading & operator=(Reading const & other) {
    elevation = other.elevation;
    payloadString = std::ostringstream{other.payloadString.str()};
    speed = other.speed;
    return *this;
}

std::ostringstream は移動可能であることに注意してください。これは、コンパイラが の移動コンストラクターと移動代入演算子を自動的に生成することを意味しReadingます。fakeReadingしたがって、リスト要素を次のように移動構築できます。

readingsList.emplace_back(std::move(fakeReading));

コピー コンストラクター/代入を実装することを選択した場合、コンパイラはムーブ コンストラクター/代入を生成しないため、それらを生成するようにコンパイラに明示的に指示する必要があります。

Reading(Reading &&) = default;
Reading & operator=(Reading &&) = default;
于 2020-07-10T01:27:28.897 に答える