您是应该将自动副本移动到成员中还是单独留下?

时间:2013-12-12 19:09:42

标签: c++ c++11 move-semantics

如果你要复制一些要存储在课堂上的东西,比如:

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。)

1 个答案:

答案 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/

(请注意,这是一系列文章,我错过了开头的链接!)