場合によります。関数への入力で左辺値を渡す場合(実際には、address-of演算子&を適用できる名前を持つものを渡す場合)、クラスのコピーコンストラクターが呼び出されます。
void foo(vector<char> v)
{
...
}
int bar()
{
vector<char> myChars = { 'a', 'b', 'c' };
foo(myChars); // myChars gets COPIED
}
右辺値(大まかに言って、名前がなく、アドレス演算子&を適用できないもの)を渡していて、クラスにmoveコンストラクターがある場合、オブジェクトは移動されます(これは注意してください)。 、「エイリアス」を作成するのと同じですが、オブジェクトの内臓を新しいスケルトンに転送して、前のスケルトンを役に立たなくします)。
以下の呼び出しではfoo()
、の結果make_vector()
は右辺値です。したがって、それが返すオブジェクトは、への入力で与えられたときに移動foo()
されます(つまり、vector
の移動コンストラクターが呼び出されます)。
void foo(vector<char> v);
{
...
}
vector<char> make_vector()
{
...
};
int bar()
{
foo(make_vector()); // myChars gets MOVED
}
一部のSTLクラスには、移動コンストラクターがありますが、コピーコンストラクターはありません。これは、本質的にコピー不可であることが意図されているためです(たとえばunique_ptr
)。unique_ptr
関数に渡すときに、のコピーを取得することはできません。
コピーコンストラクターを持つクラスの場合でも、std::move
関数を使用して引数を左辺値から右辺値に変更することで、移動セマンティクスを強制できますが、エイリアスは作成されず、オブジェクトの所有権が転送されるだけです。呼び出している関数に。つまり、元のオブジェクトに別の値を再割り当てするか、オブジェクトを破棄する以外に、元のオブジェクトで他のことを行うことはできません。
例えば:
void foo(vector<char> v)
{
...
}
vector<char> make_vector()
{
...
};
int bar()
{
vector<char> myChars = { 'a', 'b', 'c' };
foo(move(myChars)); // myChars gets MOVED
cout << myChars.size(); // ERROR! object myChars has been moved
myChars = make_vector(); // OK, you can assign another vector to myChars
}
左辺値と右辺値の参照のこの主題全体と移動のセマンティクスがあいまいであることがわかった場合、それは非常に理解できます。私は個人的にこのチュートリアルが非常に役立つと感じました:
http://thbecker.net/articles/rvalue_references/section_01.html
http://www.isocpp.orgまたはYouTube(Scott Meyersによるセミナーを探してください)でもいくつかの情報を見つけることができるはずです。