如果你要复制一些要存储在课堂上的东西,比如:
struct S {
S(std::vector<int> v);
private:
std::vector<int> m; // gonna store v in here
};
我听说你应该让编译器按值v
为你制作副本,因为它有时可以更高效地完成它。但是,在构造函数的成员初始化列表中,您应该使用m
还是v
初始化std::move(v)
?如果v
的类型是仅移动类型怎么办? (在后一种情况下,我假设您必须使用move
。)
答案 0 :(得分:1)
如果它只是移动的话,那么你最好的做法就是按价值取出参数,然后再移动。
当v的类型可以复制或移动时,我会将“最佳实践”的状态描述为有点流畅,目前有不同的思想流派。但是,我认为,这被认为是编写您需要的最佳移动感知构造函数的方法。
我会说,做你在这里所做的事情,是的,使用移动演员从rvalue初始化成员。
当您使用构造函数时,请尝试利用copy-elision。例如,这个:
struct S {
S(std::vector<int> v) : m(std::move(v)) {}
private:
std::vector<int> m;
};
std::vector<int> create_vector()
{
std::vector<int> vec = // initialisation stuff
return vec;
}
int main()
{
S instance_of_s{create_vector()};
return 0;
}
理想情况下,由于各种复制方式,理想情况下不应复制任何内容。但当然,这取决于编译器。
这是一个证明这一点的例子。
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
class VectorWrapper
{
public:
VectorWrapper() : vec(){}
VectorWrapper(const VectorWrapper& other) : vec(other.vec){ cout << "COPY" << endl; }
VectorWrapper(VectorWrapper&& other) : vec(move(other.vec)){ cout << "MOVE" << endl; }
private:
vector<int> vec;
};
struct S
{
S(VectorWrapper v) : m(move(v)) {}
private:
VectorWrapper m;
};
int main()
{
S instance_of_s{VectorWrapper()};
return 0;
}
根据GCC 4.7.2,输出为:
MOVE
参考文献:
http://cpptruths.blogspot.co.uk/2012/03/rvalue-references-in-constructor-when.html
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
(请注意,这是一系列文章,我错过了开头的链接!)