2012-12-28 10 views
7

STLコンテナを渡すとコンテナのコピーを作成するのか、別の別名だけをコピーするのかを覚えていません。私はカップルのコンテナがある場合:合格STLコンテナはコピーを作成しますか?

void SomeClass::someFunction(std::vector<char> characterStuff); 

またはこのunordered_mapのコピーを作成します/:

std::unordered_map<int,std::string> _hashStuff; 
std::vector<char> _characterStuff; 

をそして、私は関数にこれらの変数を渡したい、私はそうとして機能させることができますvector?私はshared_ptrを使う必要があると思っています。

void SomeClass::someFunction(std::shared_ptr<std::vector<char>> characterStuff); 
+0

あなたのシングルコロン ':'はダブルコロン '::'ではないでしょうか? – 0x499602D2

+0

@Davidはい、それらは二重コロン '::'でなければなりません。 –

+0

参照渡しのコピーパス(好ましくはconst参照)を防ぐためです。 –

答えて

7

です。 左辺を関数に渡す場合(実際には、住所の演算子&が適用される名前を持つものを渡している場合)、クラスのコピーコンストラクタが呼び出されます。

void foo(vector<char> v) 
{ 
    ... 
} 

int bar() 
{ 
    vector<char> myChars = { 'a', 'b', 'c' }; 
    foo(myChars); // myChars gets COPIED 
} 

あなたはその後、右辺値(大体、名前を持っていないと、そのアドレス演算子&を適用することができないために何か)とクラスが移動コンストラクタを持ち、オブジェクトを渡す場合(エイリアスを作成するのと同じではなく、オブジェクトの勇気を新しいスケルトンに移して、前のスケルトンを無用にします)。

以下のfoo()の呼び出しでは、make_vector()の結果はの値です。

void foo(vector<char> v); 
{ 
    ... 
} 

vector<char> make_vector() 
{ 
    ... 
}; 

int bar() 
{ 
    foo(make_vector()); // myChars gets MOVED 
} 

いくつかのSTLクラスは、移動コンストラクタを持っていますが、はコピーを持っていない。したがって、それは返すオブジェクト(つまりvectorの移動コンストラクタが呼び出されます)foo()への入力で与えられたときを移動されています本質的にコピー不可能であることを意図しているので(例えば、unique_ptr)、コンストラクタがあります。あなたはそれを関数に渡すときにunique_ptrのコピーを手に入れません。

コピーコンストラクタを持つクラスであっても、std::move関数を使用してlvalueからrvalueに引数を変更することで強制的にセマンティクスを強制できますが、別名を作成せずに転送します呼び出す関数へのオブジェクトの所有権。つまり、別の値に再割り当てしたり、破棄したりする以外に、元のオブジェクトで他の操作を行うことはできません。例えば

:あなたは左辺値と右辺値参照のこの全体の主題を見つけて、あいまいなセマンティクスを移動した場合

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にもいくつかの情報を見つけることができるはずです(スコット・マイヤーズセミナーを探してください)。

+1

ここでのすべての回答は私が答えとして記されていると十分に考えていますが、私はあなたのものが最も興味深いものであることを発見しました。 –

+0

ありがとう!とにかく、いくつかの良い素材を読んだ後にこの物を掴むための最良の方法は、少し試してみることです。小さなコンストラクタとコピーコンストラクタを使って小さなおもちゃクラスを作成し、値によっていくつかの関数に渡し、どれが呼び出されたのかを確認することをお勧めします(デバッグや内部に 'cout << msg'を入れて)。上記の 'make_vector()'から戻るときのように、コンストラクタがまったく呼び出されないことがあることに気づくでしょう:それは最適化コンパイラが通常行うことです –

5

はい、値渡しのためベクターをコピーします。値を渡すと常にコピーや移動が行われます(これは特定の条件の下では省略される可能性がありますが、あなたのケースでは省略される可能性があります)。関数内の同じベクトルを外部と参照したい場合は、代わりに参照渡しすることができます。タイプstd::vector<char>&は「std::vector<char>への参照」、参照型である

void SomeClass::someFunction(std::vector<char>& characterStuff); 

:あなたの関数は、に変更します。 characterStuffという名前は、_characterStuffによって参照されるオブジェクトの別名として機能します。

+0

Nitpick:値渡しとは思わない*常に*コピーを作る。例えば、値を一時的に渡すとき、私はコンパイラがコピーを削除することができると確信しています。 –

+0

@BjörnPollexはい!私はそれに言及するのを忘れていた。 –

4

C++は値に基づいています。オブジェクトを値渡しすると、独立したコピーが得られます。呼び出された関数は、引数を変更できないようにする必要がありますが、あなたがしたくない場合は

void SomeClass::someFunction(std::vector<char>& changable) { ... } 
void SomeClass::otherFunction(std::vector<char> const& immutable) { ... } 

:あなたはコピーを取得したくない場合は、代わりに参照またはconst参照し、使用することができますオブジェクトのコピーを作成する場合は、const&を渡すことをお勧めします。通常、代わりにstd::shared_ptr<T>のようなものは使用しません。関数を呼び出すときにコピーを妨げないように、この型の使用があります。

関連する問題