C++ c++;为什么在移动构造函数时需要移动/前进
在使用移动构造函数构造对象之后,新对象应该“窃取”“源”对象的资源,然后将其保留在不确定(但有效)状态 例如:C++ c++;为什么在移动构造函数时需要移动/前进,c++,move-semantics,rvalue,C++,Move Semantics,Rvalue,在使用移动构造函数构造对象之后,新对象应该“窃取”“源”对象的资源,然后将其保留在不确定(但有效)状态 例如: #include <iostream> #include <vector> template <class T> void print(const std::vector<T>& v) { std::cout << "size = " << v.size() << " vector =
#include <iostream>
#include <vector>
template <class T>
void print(const std::vector<T>& v)
{
std::cout << "size = " << v.size() << " vector = ";
for (const auto& x : v)
std::cout << x << " ";
std::cout << std::endl;
}
int main()
{
std::vector<int> data(10, 3);
std::cout << "data:" << std::endl;
print(data);
std::vector<int> data2(std::move(data));
std::cout << "data2:" << std::endl;
print(data2);
std::cout << "data after moving:" << std::endl;
print(data);
return 0;
}
现在考虑一下上面程序的细微变化:
#include <iostream>
#include <vector>
class A {
std::vector<int> m_data;
public:
A(std::vector<int>&& data) : m_data{data} { }
const std::vector<int>& data() const { return m_data; }
};
template <class T>
void print(const std::vector<T>& v)
{
std::cout << "size = " << v.size() << " vector = ";
for (const auto& x : v)
std::cout << x << " ";
std::cout << std::endl;
}
int main()
{
std::vector<int> data(10, 3);
std::cout << "data:" << std::endl;
print(data);
A x{std::move(data)};
std::cout << "x.data():" << std::endl;
print(x.data());
std::cout << "data after moving:" << std::endl;
print(data);
return 0;
}
data:
size = 10 vector = 3 3 3 3 3 3 3 3 3 3
x.data():
size = 10 vector = 3 3 3 3 3 3 3 3 3 3
data after moving:
size = 10 vector = 3 3 3 3 3 3 3 3 3 3
看起来向量数据
刚刚被复制到A::m_data
而不是被移动
如果我用
A(std::vector<int>&& data) : m_data{std::move(data)} { }
换句话说,似乎需要std:move
或std::forward
来有效地调用A::m_data
的移动构造函数。std::move
和std::forward
都将static_cast
返回到std::vector&
,但是a
的移动构造函数的参数已经是右值
为什么需要额外的
std::move
或std::forward
呢?首先,您应该知道A::A(std::vector&data)
意味着数据是对std::vector
的右值引用,只是指引用而不是调用move构造函数
而
A(std::vector&data):m_data{data}{}
只是调用m_data
的复制构造函数,因为data
本身在A::A
的范围内是一个命名值而不是r值
临时值,因此std::move
或std::forward
是必要的。或等A(std::vector&data):m_data{data},m_data2{data}{}
是完全合法的,所以第一件事最好不要删除数据
!!将数据
用作表达式时,此表达式的类型将调整为非引用类型std::vector
。没有&
,没有&
。编译器应该如何知道调用哪个构造函数?价值范畴<代码>数据具有左值类别,无法绑定到移动构造函数中的std::vector&
。要更改值类别,请使用move:std::move(data)
具有xvalue类别,并且可以绑定到std::vector&
。这将是一个更好的匹配比复制。看看这听起来是否令人困惑。
A(std::vector<int>&& data) : m_data{std::move(data)} { }
A(std::vector<int>&& data) : m_data{std::forward<std::vector<int>&&>(data)} { }
data:
size = 10 vector = 3 3 3 3 3 3 3 3 3 3
x.data():
size = 10 vector = 3 3 3 3 3 3 3 3 3 3
data after moving:
size = 0 vector =