これは
struct Example {
int a, b;
Example(int mA, int mB) : a{mA}, b{mB} { }
Example(const Example& mE) : a{mE.a}, b{mE.b} { }
Example(Example&& mE) : a{move(mE.a)}, b{move(mE.b)} { }
Example& operator=(const Example& mE) { a = mE.a; b = mE.b; return *this; }
Example& operator=(Example&& mE) { a = move(mE.a); b = move(mE.b); return *this; }
}
これと同等
struct Example {
int a, b;
Example(int mA, int mB) : a{mA}, b{mB} { }
Example(const Example& mE) = default;
Example(Example&& mE) = default;
Example& operator=(const Example& mE) = default;
Example& operator=(Example&& mE) = default;
}
?
はい、両方とも同じです。
しかし
struct Example {
int a, b;
Example(int mA, int mB) : a{mA}, b{mB} { }
Example(const Example& mE) = default;
Example(Example&& mE) = default;
Example& operator=(const Example& mE) = default;
Example& operator=(Example&& mE) = default;
}
このバージョンでは、本文の定義をスキップできます。
ただし、explicitly-defaulted-functions
を宣言するときは、いくつかの規則に従う必要があります。
8.4.2明示的にデフォルト設定された関数[dcl.fct.def.default]
次の形式の関数定義:
attribute-specifier-seqopt decl-specifier-seqopt declarator virt-specifier-seqopt = default ;
explicitly-defaulted定義と呼ばれます。明示的にデフォルト設定されている関数は
特別なメンバー関数である、
同じ宣言された関数型を持ちます(異なるref-qualifiersを除く)。ただし、コピーコンストラクターまたはコピー割り当て演算子の場合は、パラメーター型「非const
T
への参照」の場合があります。ここで、T
は、暗黙的に宣言されているかのように、メンバー関数のクラスの名前です。デフォルト引数はありません。
はい、デフォルトの移動コンストラクターは、そのベースとメンバーのメンバーごとの移動を実行します。
Example(Example&& mE) : a{move(mE.a)}, b{move(mE.b)} { }
以下と同等です:
Example(Example&& mE) = default;
ドラフトC++ 11標準 セクション12.8
クラスオブジェクトのコピーと移動パラグラフ1これは(今後のエンファシスマイニング):
デフォルトであり、削除済みとして定義されていないコピー/移動コンストラクターが暗黙的に定義されているは、もし修正された場合(3.2)または最初の宣言後に明示的にデフォルトになった場合です。 [注:実装がそのodr-use(3.2、12.2)を省略した場合でも、コピー/移動コンストラクターは暗黙的に定義されます。 —注を終了] [...]
段落15は次のとおりです。
implicitly-defined copy/move constructornon-union class Xは、そのベースとメンバーのメンバーごとのコピー/移動を実行します。 [注:非静的データメンバーのbrace-or-equal-initializerは無視されます。 12.6.2の例を参照してください。 —end note]初期化の順序は、ユーザー定義コンストラクターのベースとメンバーの初期化の順序と同じです(12.6.2を参照)。 xをコンストラクターのパラメーター、または移動コンストラクターの場合は、パラメーターを参照するxvalueとします。各ベースまたは非静的データメンバは、そのタイプに適した方法でコピー/移動されます。
- メンバーが配列の場合、各要素はxの対応するサブオブジェクトで直接初期化されます。
- メンバーmに右辺値参照型T &&がある場合、static_cast(x.m)で直接初期化されます。
- それ以外の場合、ベースまたはメンバーは、xの対応するベースまたはメンバーで直接初期化されます。
仮想基本クラスのサブオブジェクトは、暗黙的に定義されたコピー/移動コンストラクターによって一度だけ初期化されます(12.6.2を参照)。
=default
移動コンストラクターは、メンバーごとの移動コンストラクターと同等ですか?
はい。 更新:さて、常にではありません。この例を見てください:
#include <iostream>
struct nonmovable
{
nonmovable() = default;
nonmovable(const nonmovable &) = default;
nonmovable( nonmovable &&) = delete;
};
struct movable
{
movable() = default;
movable(const movable &) { std::cerr << "copy" << std::endl; }
movable( movable &&) { std::cerr << "move" << std::endl; }
};
struct has_nonmovable
{
movable a;
nonmovable b;
has_nonmovable() = default;
has_nonmovable(const has_nonmovable &) = default;
has_nonmovable( has_nonmovable &&) = default;
};
int main()
{
has_nonmovable c;
has_nonmovable d(std::move(c)); // prints copy
}
以下を印刷します:
copy
http://coliru.stacked-crooked.com/a/62c0a0aaec15b0eb
デフォルトの移動コンストラクターを宣言しましたが、移動ではなくコピーが発生します。どうして?クラスに単一の非可動メンバーさえある場合、explicitlydefaultedmove constructor is暗黙的にdeleted(このようなしゃれ)。したがって、has_nonmovable d = std::move(c)
を実行すると、has_nonmovable
の移動コンストラクターが(暗黙的に)削除されるため、コピーコンストラクターが実際に呼び出されます(式has_nonmovable(has_nonmovable &&) = default
)。
ただし、non_movable
の移動コンストラクターがまったく宣言されていない場合、移動コンストラクターはmovable
(および移動コンストラクターを持つすべてのメンバー)に使用され、コピーコンストラクターはnonmovable
(および移動コンストラクターを定義していないすべてのメンバーに対して)。例を参照してください。
#include <iostream>
struct nonmovable
{
nonmovable() = default;
nonmovable(const nonmovable &) { std::cerr << "nonmovable::copy" << std::endl; }
//nonmovable( nonmovable &&) = delete;
};
struct movable
{
movable() = default;
movable(const movable &) { std::cerr << "movable::copy" << std::endl; }
movable( movable &&) { std::cerr << "movable::move" << std::endl; }
};
struct has_nonmovable
{
movable a;
nonmovable b;
has_nonmovable() = default;
has_nonmovable(const has_nonmovable &) = default;
has_nonmovable( has_nonmovable &&) = default;
};
int main()
{
has_nonmovable c;
has_nonmovable d(std::move(c));
}
以下を印刷します:
movable::move
nonmovable::copy
http://coliru.stacked-crooked.com/a/420cc6c80ddac407
更新:しかし、has_nonmovable(has_nonmovable &&) = default;
行をコメントアウトすると、両方のメンバーにコピーが使用されます: http: //coliru.stacked-crooked.com/a/171fd0ce335327cd -印刷:
movable::copy
nonmovable::copy
おそらく、=default
をどこにでも置くことは、まだ理にかなっています。移動式が常に移動するという意味ではありませんが、この可能性が高くなります。
もう1つの更新:しかし、has_nonmovable(const has_nonmovable &) = default;
行をコメントアウトすると、結果は次のようになります。
movable::move
nonmovable::copy
したがって、プログラムで何が起こるかを知りたい場合は、自分ですべてをしてください:ため息: