传递STL容器会复制吗?

Mr.*_*ith 10 c++ c++11

我不记得传递一个STL容器是否复制了容器,或者只是另一个别名.如果我有几个容器:

std::unordered_map<int,std::string> _hashStuff;
std::vector<char> _characterStuff;
Run Code Online (Sandbox Code Playgroud)

我想将这些变量传递给一个函数,我可以这样做:

void SomeClass::someFunction(std::vector<char> characterStuff);
Run Code Online (Sandbox Code Playgroud)

或者这会复制unordered_map/ vector?我想我可能需要使用shared_ptr.

void SomeClass::someFunction(std::shared_ptr<std::vector<char>> characterStuff);
Run Code Online (Sandbox Code Playgroud)

And*_*owl 9

这取决于.如果要在函数的输入中传递左值(实际上,如果传递的是具有名称的东西,可以应用地址的运算符),那么将调用类的复制构造函数.

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

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

如果你传递的是一个rvalue(粗略地说,没有名字的东西,运算符的地址并且不能应用),并且该类有一个移动构造函数,那么该对象将被移动(不是,请注意,与创建"别名"相同,而是将对象的内容转移到新的骨架中,使之前的骨架变得无用).

foo()下面的调用中,结果make_vector()rvalue.因此,当在输入中给出时,它返回的对象被移动foo()(即,vector将调用移动构造函数):

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

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

int bar()
{
    foo(make_vector()); // myChars gets MOVED
}
Run Code Online (Sandbox Code Playgroud)

一些STL类有一个移动构造函数但没有复制构造函数,因为它们本身就是不可复制的(例如unique_ptr).将unique_ptr函数传递给函数时,不会得到a的副本.

即使对于那些具有复制构造函数的类,您仍然可以通过使用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
}
Run Code Online (Sandbox Code Playgroud)

如果你发现lvalue和rvalue引用的整个主题并且移动语义模糊不清,那是非常容易理解的.我个人认为本教程非常有帮助:

http://thbecker.net/articles/rvalue_references/section_01.html

您也应该能够在http://www.isocpp.org或YouTube 上找到一些信息(寻找Scott Meyers的研讨会).


Jos*_*eld 5

是的,它会复制矢量,因为你正在通过值传递.通过值传递总是复制或移动(在某些条件下可能会被删除,但在您的情况下则不然).如果要在函数内部引用与外部相同的向量,则可以通过引用将其传递给它.将您的功能更改为:

void SomeClass::someFunction(std::vector<char>& characterStuff);
Run Code Online (Sandbox Code Playgroud)

类型std::vector<char>&是引用类型,"引用std::vector<char>".该名称characterStuff将充当所引用对象的别名_characterStuff.


Die*_*ühl 5

C++ 基于值:当按值传递对象时,您将获得独立的副本。如果您不想获取副本,可以使用参考或参考const,而不是:

void SomeClass::someFunction(std::vector<char>& changable) { ... }
void SomeClass::otherFunction(std::vector<char> const& immutable) { ... }
Run Code Online (Sandbox Code Playgroud)

当被调用的函数不应该能够更改参数但您不想创建对象的副本时,您需要传递const&. 通常,我不会使用类似 a 的东西std::shared_ptr<T>来代替。这种类型的用途当然不是为了防止调用函数时进行复制。