2016-12-29 5 views
1
class N { 
public: 
    N() = default; 
    N(const N& n) { std::cout << "N copy\n"; }; 
private: 
    char c; 
}; 

class H { 
public: 
    H() = default; 
    H(H&) { std::cout << "H copy\n"; } 
    H(H&&) = default; 
private: 
    N n; 
}; 

int main() { 
    N n1, n2 = std::move(n1); 
    H h1, h2 = std::move(h1); 
} 

VS2016では、クラスNを定義して、ムーブコンストラクタがコンパイラによって定義も合成もされていない場合の動作を確認します。デフォルトの移動コンストラクタが削除された場合に何が起こるかを見るためにクラスHを定義します。私は理解できない何デフォルトの移動コンストラクタを削除する必要があるときに混乱するもの

があるN.には移動コンストラクタがありませんので、最初の文を印刷、コピーコンストラクタを意味し、「Nのコピー」を、実行する主な機能には

は、第二の文を実行し、呼ばれます"h2 = std :: move(h1)"は "N copy"も出力します。

私はC++ Primer(C++ 11をベースにしています)で読んだように、クラスに独自のコピーコンストラクタを定義するメンバがあるのに、クラスのデフォルトのムーブコンストラクタは削除されていますが、移動コンストラクタを定義します。メンバnがその条件を満たしているので、Hの移動コンストラクタを削除する必要があります。 "h2 = std :: move(h1)"はコピーコンストラクタを呼び出し、 "H copy"を出力します。

ただし、 "N copy"のみが出力されます。つまり、Hのコピーコンストラクタは呼び出されませんが、Nのコピーコンストラクタが呼び出されます。どうして?ここで


は私が推測するものです:

コンパイラはまだHのための移動のコンストラクタを合成し、それは次のように動作します。

ここ
H(H&& h) :n(std::move(h.n)) {} 

移動コンストラクタは、メンバーnを移動しようとすると、 "N n1、n2 = std :: move(n1);"で起きたように、Nのコピーコンストラクタが呼び出され、 "N copy"が出力されます。


この説明は、意味を成さないが、C++入門によると、Hのデフォルトの移動のコンストラクタは、削除のように定義されている必要があります。これは呼び出されるべきHのコピーコンストラクタです。

私は混乱しています:本は間違っていますか?それとも、新しい標準によって導入された新しいプロパティですか?または、これはコンパイラによって引き起こされますか?

+0

[コアの問題1402](https://wg21.link/CWG1402)です。 –

+0

ありがとう、私はこれがC++によってもたらされた何らかの修正であることを理解しています。 – Dardai

答えて

1

あなたはどんな驚きですか?あなたはHのためのデフォルトの移動コンストラクタを持っています、そして、それはすべてのメンバーのための移動またはコピーコンストラクタを呼び出すでしょう。メンバは1つしかありませんが、Nは移動コンストラクタを持たないため、コピーコンストラクタNが呼び出されます。これが印刷物を見る理由です。

+0

C++ Primerによれば、Hのデフォルトの移動コンストラクタはdeleteとして定義されていたはずですが、結果は削除されていないことを示しているので、私は驚いています。 – Dardai

+0

ありがとう、私はこれがC++によってもたらされた何らかの修正であることを理解しています。 – Dardai

関連する問題