我有一个类似<{1}}的类
std::vector
我创建像
这样的对象struct Mystruct
{
Mystruct(const std::vector<int>& w): v(w)
{
std::cout << "Copy constructor :" << v.at(0) << "\n";
}
Mystruct(const std::vector<int>&& w): v(w)
{
std::cout << "Move Constructor :" << v.at(0) << "\n";
}
private:
std::vector<int> v;
};
int main()
{
auto x = std::vector<int> {1,2,3};
Mystruct M1(x);
Mystruct M2(std::vector<int> {3,2,1});
return 0;
}
使用复制构造函数构建,M1
使用&#34;移动&#34;构造函数,但是在gdb中运行时,两个assignements都为v和w保留不同的地址,如果我在第二个构造函数的初始化列表中使用v(std :: move(w)),则会发生同样的情况。所以我猜两个人都在复制w的内容,这是正确的吗?如果是这种情况,我怎样才能移动w的内容而不是复制它们
答案 0 :(得分:12)
首先,移动对象不会改变其地址。根据定义,您不能更改对象的地址,因为地址是对象定义的一部分。如果您有不同的地址,则会有不同的对象。什么移动(至少在标准库中的类)是移动对象的动态分配资源的所有权。
其次,你没有动任何东西。为了移动东西,你必须调用移动构造函数。这意味着你需要传递一个r值。命名对象永远不是r值。因此,即使您有r值引用,仍需要使用std::move
进行转换。但在你的情况下,即使这还不够。在标准库中,所有移动构造函数都具有Type(Type&&)
的签名,而不是Type(const Type&&)
。如果传递一个const值,即使用std::move
强制转换它,它也会调用复制构造函数,而不是移动构造函数。为了调用移动构造函数,您的对象不能是const。
因此,移动向量 * 的构造函数应如下所示:
Mystruct(std::vector<int>&& w): v(std::move(w))
{
std::cout << "Move Constructor :" << v.at(0) << "\n";
}
为了比较地址以查看它是否实际被移动,您不应该比较v
和w
的地址(那些不会,也不能更改),但是{{1 }和v.data()
,它指向向量的动态分配资源。
*不是移动构造函数。移动构造函数将具有签名w.data()
或Mystruct(Mystruct&&)