我有一个关于在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>&&
构造函数吗?
答案 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);
这将导致像你的例子一样移动,没有人会期待这一举动。