使用std ::移动向量

Using std::move with vectors

本文关键字:向量 移动 使用 std      更新时间:2023-10-16

我有一个关于在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>&&的构造函数?

您的第二个方案很好。

向量将仅使用第二版移动两次(将副价值参数移至您的成员中)。如果您不介意额外动作的成本,则可以坚持将副价值参数移至您的会员。

如果您介意,请为参数的不同值类别制作两个构造函数。

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

class A
{
public:
    A(const std::vector<char>& v_) : v(v_) { std::cout << "const& ctorn"; }
    A(std::vector<char>&& v_) : v(std::move(v_)) { std::cout << "rvalue&& ctorn"; }
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;
}

输出:

const&amp;ctor

rvalue&amp;&amp;ctor

多次使用向量,您可以通过价值接受vector并从中移动。所以,

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

但是,这假定您仅为"自然" lvalues或临时性来称呼它。意思是,它将是

之类的案例的性能
A a(std::vector<char>{....}); // <--- 1
std::vector<char> my_vec;
A b(my_vec); // <--- 2

如果您期望用一个您想从示例中移动的lvalue,而不是需要两个构造函数 - 带有const lvalue参考和rvalue参考:

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

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

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

如果您没有写那本书,则在这里再收到一份副本。

您必须记住,您的向量将"离开"。因此,如果您写类似:

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

因此,您的向量V不应在A的构造函数A的呼叫之后使用。所有元素都移开了,迭代器对内容无效。向量可用于存储新数据。

所以如果您写

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

这将导致像您的示例一样的举动,没有人会期望这一举动。