13

Visual Studio 2012 Update 2 を使用していますが、std::vector が unique_ptr のコピー コンストラクターを使用しようとしている理由を理解するのに苦労しています。私は同様の問題を見てきましたが、ほとんどは明示的な移動コンストラクターおよび/または演算子がないことに関連しています。

メンバー変数を文字列に変更すると、移動コンストラクターが呼び出されたことを確認できます。ただし、unique_ptr を使用しようとすると、コンパイル エラーが発生します。

error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'.

誰かが私が欠けているものを教えてくれることを願っています、ありがとう!

#include <vector>
#include <string>
#include <memory>

class MyObject
{
public:
    MyObject() : ptr(std::unique_ptr<int>(new int))
    {
    }

    MyObject(MyObject&& other) : ptr(std::move(other.ptr))
    {
    }

    MyObject& operator=(MyObject&& other)
    {
        ptr = std::move(other.ptr);
        return *this;
    }

private:
    std::unique_ptr<int> ptr;
};

int main(int argc, char* argv[])
{
    std::vector<MyObject> s;
    for (int i = 0; i < 5; ++i)
    {
        MyObject o;
        s.push_back(o);
    }

    return 0;
}
4

2 に答える 2

15

このpush_back()関数は、引数を値で受け取ります。push_back()したがって、 (左辺値を渡す場合) の引数をコピー構築するか、(右辺値を渡す場合) を移動構築する試みが行われます。

この場合、oは左辺値 (名前付きオブジェクトは左辺値であるため)であり、右辺値参照は左辺値にバインドできません。したがって、コンパイラは移動コンストラクターを呼び出すことができません。

オブジェクトを移動するには、次のように記述する必要があります。

s.push_back(std::move(o));
//          ^^^^^^^^^

この場合、私が驚いたのは、VC11がコピーコンストラクターを削除MyObject済みとして定義せずに暗黙的に生成したように見えることです(投稿したエラーから判断)。クラスが移動コンストラクターを宣言しているため、これは当てはまりません。C++11 標準のパラグラフ 12.8/7 によると、実際には次のようになります。

クラス定義でコピー コンストラクターが明示的に宣言されていない場合は、暗黙的に宣言されます。クラス定義でムーブ コンストラクターまたはムーブ代入演算子が宣言されている場合、暗黙的に宣言されたコピー コンストラクターは deleted として定義されます。それ以外の場合は、デフォルトとして定義されます (8.4)

push_back()右辺値を渡していないため、発生しているエラーは正しいものの、 VC11 はここでは完全に準拠していないと結論付けなければなりません。

于 2013-04-15T08:24:22.013 に答える