传递STL容器会复制吗?

时间:2012-12-28 18:51:56

标签: c++ c++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);

3 个答案:

答案 0 :(得分:9)

这取决于。如果您在函数的输入中传递左值(实际上,如果您传递的是具有名称的东西,可以应用地址的运算符&amp;)那么复制构造函数你的课程将被调用。

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

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

如果你传递 rvalue (粗略地说,某些东西没有名称,并且运算符和地址不能被应用)并且该类有一个移动构造函数,那么对象将被移动(这不是,要小心,与创建“别名”相同,而是将对象的内容转移到新的骨架中,使之前的骨架无用)。

在下面foo()的调用中,make_vector()的结果是 rvalue 。因此,当在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 } 函数将参数从左值更改为右值来强制移动语义,但同样不会创建别名,它只是将对象的所有权转移到您正在调用的函数。这意味着除了将其重新分配给另一个值或将其销毁之外,您将无法对原始对象执行任何其他操作。

例如:

{{1}}

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

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

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

答案 1 :(得分:5)

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

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

类型std::vector<char>&是引用类型,“对std::vector<char>的引用”。名称characterStuff将充当_characterStuff引用的对象的别名。

答案 2 :(得分:4)

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

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

当被调用函数不能更改参数但您不想创建对象的副本时,您需要通过const&。通常情况下,我不会使用std::shared_ptr<T>之类的东西。这种类型的用途肯定不会在调用函数时阻止复制。