我无法记住传递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);
答案 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>
之类的东西。这种类型的用途肯定不会在调用函数时阻止复制。