5

コピー構築とコピー割り当てでディープコピーを実行する大きなオブジェクトを管理するコンテナーを作成したいと考えています。

template <class TBigObject>
class Container : public std::vector< std::shared_ptr<TBigObject> >
{
public:
    Container(int nToAllocate){ /* fill with default constructed TBigObjects */ }
    Container(const Container& other){ /* deep copy */ }
    Container(Container&&) = default;
    Container& operator = (const Container& population){ /* deep copy */ }
    Container& operator = (Container&&) = default;
};

デフォルトの動作を知りたい:

Container(Container&&) = default;
Container& operator = (Container&&) = default;

メンバーは実際にそうしています。

私が電話した場合:

Container<int> makeContainer()
{
    ...
}

次の場所にデバッグ ブレークポイントを設定します。

Container<int> moveAssigned; 
moveAssigned = makeContainer(); // EDIT corrected thanks to Andy Prowl
Container<int> moveConstructed(makeContainer());

コピー コンストラクターと代入演算子の内部では、デバッガーはこれらのブレークポイントを飛び越えます。そのため、デフォルトの移動メンバーは実際にはディープ コピーを実行せず、すべてのサブオブジェクトを移動しているようです。

この動作は標準で保証されていますか? デフォルトの移動メンバーは直感的に動作し、すべてのサブオブジェクトを移動しますか?

4

1 に答える 1

8

デフォルトの移動メンバーは直感的に動作し、すべてのサブオブジェクトを移動しますか?

はい。C++11 標準のパラグラフ 12.7/15 によると:

非共用体クラス X の暗黙的に定義されたコピー/移動コンストラクターは、その基底とメンバーのメンバーごとのコピー/移動を実行します。[...]

ちなみにこれ:

Container<int> moveAssigned = makeContainer();

移動代入ではなく、コピー初期化構文を使用する移動構築です。移動の割り当ては次のようになります。

Container<int> moveAssigned;
// ...
moveAssigned = makeContainer(); // <== MOVE ASSIGNMENT HERE

これの違い:

Container<int> c(make_container());

この:

Container<int> c = make_container();

概念的には、2 番目のケースでは、タイプの一時オブジェクトがContainer<int>最初に右側の式から構築され、次にcこの一時からムーブ構築されます。

最初のケースでは、直接の初期化があります。つまり、cによって返されるオブジェクトから直接構築されmake_container()ます。

「概念的に」という言葉を強調した理由は、実際には、コンパイラーはコピー省略を実行できるため、2 番目のバージョンは最初のバージョンに最適化される可能性が高いためです (ただし、コピー コンストラクターまたはムーブ コンストラクターのアクセシビリティは引き続きチェックする必要があります)。コンパイラによって)。

于 2013-05-13T12:11:09.157 に答える