11

STL コンテナーを渡すとコンテナーのコピーが作成されるのか、それとも単に別のエイリアスが作成されるのか思い出せません。いくつかのコンテナーがある場合:

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

そして、これらの変数を関数に渡したいのですが、関数を次のように作成できますか:

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

unordered_mapまたは、これは/のコピーを作成しますvectorか? を使用する必要があるかもしれないと考えていますshared_ptr

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

3 に答える 3

12

場合によります。関数への入力で左辺値を渡す場合(実際には、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によるセミナーを探してください)でもいくつかの情報を見つけることができるはずです。

于 2012-12-28T20:04:08.733 に答える
6

はい、値で渡しているため、ベクターがコピーされます。値を渡すと、常にコピーまたは移動が行われます(特定の条件下では省略される場合がありますが、あなたの場合はそうではありません)。関数の内側と外側の同じベクトルを参照したい場合は、代わりに参照渡しするだけで済みます。関数を次のように変更します。

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

std::vector<char>&は参照型、「への参照std::vector<char>」です。この名前characterStuffは、 によって参照されるオブジェクトのエイリアスとして機能します_characterStuff

于 2012-12-28T18:53:30.550 に答える
5

C++ は値に基づいています: オブジェクトを値で渡すと、独立したコピーが取得されます。コピーを取得したくない場合はconst、代わりに参照または参照を使用できます。

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

呼び出された関数が引数を変更できないが、オブジェクトのコピーを作成したくない場合は、 を渡しconst&ます。通常、代わりに a のようなものは使用しませんstd::shared_ptr<T>。関数を呼び出すときにコピーを妨げないようにするために、このタイプの使用法があります。

于 2012-12-28T18:57:52.870 に答える