使用std :: move with vectors

时间:2016-12-23 20:56:48

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

我有一个关于在C ++中使用std::move的问题。

假设我有以下类,它在构造函数中使用std::vector作为参数:

class A
{
public:
    A(std::vector<char> v): v(v) {}
private:
    std::vector<char> v;
};

但如果我在某处写下以下内容:

std::vector<char> v;
A a(v);

std::vector的复制构造函数将被调用两次,对吗? 那么我应该为A编写构造函数,如下所示吗?

class A
{
public:
    A(std::vector<char> v): v(std::move(v)) {}
private:
    std::vector<char> v;
};

如果我想打电话给以下内容怎么办?

std::vector<char> v;
A a(std::move(v));

构造函数的第二个版本是否可以,或者我应该为A创建另一个std::vector<char>&&构造函数吗?

4 个答案:

答案 0 :(得分:1)

制作两个构造函数: 第一个构造函数应该是const&amp;,第二个构造函数应该是rvalue&amp;&amp;所以它可以使用移动语义:

class A
{
public:
    A(const std::vector<char>& v_) : v(v_) { std::cout << "const& ctor\n"; }
    A(std::vector<char>&& v_) : v(std::move(v_)) { std::cout << "rvalue&& ctor\n"; }
private:
    std::vector<char> v;
};

测试:

int main()
{
    std::vector<char> v1{ 'a', 'b', 'c', 'd' };
    A a1(v1);
    A a2(std::vector<char>{ 1, 2, 3, 4 });
   return 0;
}

输出:

  

常量&安培;构造函数

     

右值&安培;&安培;构造函数

答案 1 :(得分:1)

很多时候,通过向量接受vector并从中移动,可以很好地使用向量。所以,

A(std::vector<char> v): v(std::move(v)) {}

但是,这假设您只是为“自然”左值或临时值而调用它。意思是,对于像

这样的案例来说,它会有效
A a(std::vector<char>{....}); // <--- 1
std::vector<char> my_vec;
A b(my_vec); // <--- 2

如果你希望用你想要移动的左值来调用它,就像在你的例子中那样,需要两个构造函数 - 使用const lvalue引用和rvalue引用:

A(const std::vector<char>& v) : v(v) { }
A(std::vector<char>&& v) : v(std::move(v)) { }  

答案 2 :(得分:1)

你的第二个计划没问题。

向量将仅使用第二个版本移动两次(将by-value参数移动到您的成员中)。如果你不介意额外搬家的费用,你可以坚持只是将按值参数移动到你的会员。

如果你介意的话,那么为参数的不同值类别创建两个构造函数。

答案 3 :(得分:0)

你应该写一个移动构造函数!

A::A( std::vector<char>&& vec): v(std::move(vec) {}

如果你没有这样写,你可以在这里再复制一份。

你必须记住你的矢量会被“移开”。所以如果你写的东西如下:

std::vector<char> v;
A a(std::move(v));

所以在调用A的构造函数之后不应该使用向量v。所有元素都被移走,内容的迭代器无效。矢量可用于存储新数据。

所以,如果你写

std::vector<char> v;
A a(v);

这将导致像你的例子一样移动,没有人会期待这一举动。