如何在c++ 11中使用右值复制或别名对象
How do I copy or alias an object in C++11 using rvalues?
我想知道我对这个问题的理解是否正确,如果正确,如何解决。
我正在编写一个模板类来存储一些类型对象并对它们执行操作。问题是,我的技能仍然较差,所以即使读了11页关于价值的书,我也不能完全理解。在我的模板类中,如果我理解正确的话,一个重载的右值复制函数会使主函数中的代码在执行"cout <<"Ex.z;'被执行,因为而不是'test = move(ex);'调用左值复制函数,它会调用右值,这将导致'ex'引用什么测试引用和'test'引用什么'ex'引用?
如果这是正确的,我如何正确地实现右值对象复制功能?我之所以能够做到这一点,主要是为了创建一个正确接受右值的构造函数,而不是像我的左值构造函数那样工作,而迂回的方法是确保我理解它。
template<class T>
class Vec3
{
public:
Vec3(){}
Vec3(const Vec3 &vec):x(vec.x),y(vec.y),z(vec.z){}
void operator = (const Vec3 &other)
{x=other.x; y=other.y; z=other.z;}
// void operator = (Vec3 &&other)
// {
//this would just call the other overloaded copy function
// *this = move(other);
// }
T x, y, z;
};
main(){
Vec3<int> ex(0,0,0);
Vec3<int> test = move(ex);
test.z++;
cout << test.z;//will be 1
cout << ex.z;//will be 0
}
应该是这样的:
#include <iostream>
template<class T>
class Vec3
{
public:
Vec3() {}
Vec3(T x_, T y_, T z_): x(x_), y(y_), z(z_)
{}
Vec3(const Vec3 &vec):x(vec.x),y(vec.y),z(vec.z)
{}
Vec3(Vec3 &&vec) noexcept : x(std::move(vec.x)),y(std::move(vec.y)),z(std::move(vec.z))
{}
Vec3& operator=(const Vec3 &other)
{
x=other.x; y=other.y; z=other.z;
return *this;
}
Vec3& operator=(Vec3 &&other) noexcept
{
x = std::move(other.x);
y = std::move(other.y);
z = std::move(other.z);
return *this;
}
T x, y, z;
};
int main(){
Vec3<int> ex(0,0,0);
Vec3<int> ex1(1,1,1);
ex1 = std::move(ex); // <-- this will call move assignment operator
Vec3<int> test = std::move(ex); // <-- this will call move constructor
test.z++;
std::cout << test.z;//will be 1
std::cout << ex.z;//will be 0
return 0;
}
我个人更喜欢使用swap
习语:
#include <iostream>
template<class T>
class Vec3
{
public:
Vec3() {}
Vec3(T x_, T y_, T z_): x(x_), y(y_), z(z_)
{}
Vec3(const Vec3 &vec):x(vec.x),y(vec.y),z(vec.z)
{}
Vec3(Vec3 &&other) noexcept
{ swap(other); }
Vec3& operator=(const Vec3 &other)
{
x=other.x; y=other.y; z=other.z;
return *this;
}
Vec3& operator=(Vec3 &&other) noexcept
{
Vec3{std::move(other)}.swap(*this);
return *this;
}
void swap(Vec3 &other) noexcept
{
std::swap(x, other.x);
std::swap(y, other.y);
std::swap(z, other.z);
}
T x, y, z;
};
main(){
Vec3<int> ex(0,0,0);
Vec3<int> ex1(1,1,1);
ex1 = std::move(ex); // <-- this will call move assignment operator
Vec3<int> test = std::move(ex); // <-- this will call move constructor
test.z++;
std::cout << test.z;//will be 1
std::cout << ex.z;//will be 0
}
添加noexcept
到您的移动构造函数将受益,当在STL容器中使用std::vector
等类时。容器将使用移动而不是复制
实际上,你误解了与右值引用无关的。
简单地说,Vec3<int> test = move(ex)
将用一个参数调用Vec3<int>
的move构造函数,一个对ex
的右值引用。
要理解这一点,你必须理解std::move()
。这个模板函数所做的是接受左值引用或右值(纯右值,也就是我们所谓的"右值",因为它的起源是一个长,长)引用,并将其转换为xvalue(表达值,即可以移动数据的值)。这样的值将绑定到其类型的右值引用。
Vec3(Vec3 &&vec) : x(std::move(vec.x)), y(std::move(vec.y)), z(std::move(vec.z)) {}
您也可以将相同的原则应用于赋值操作符:
void operator=(Vec3 &&vec) {
this->x = std::move(vec.x);
this->y = std::move(vec.y);
this->z = std::move(vec.z);
}
重要的:不要简单地复制粘贴最后的代码片段!c++ 11引入了大量复杂的术语,(通常)一开始很难掌握。如果你不理解这篇文章,阅读更多的解释/例子直到你理解,否则你的大脑会调用神经病学ABI规范定义的8位智人(非图灵完全)架构,由开放自然选择组织在公元前75000年发布。
- 将包含不可复制对象的对插入到映射中
- 通用参考 l 值不复制对象
- 为什么具有 2 个参数参数的构造函数接受复制对象作为 1 个参数参数?
- 为什么从引用创建共享指针会复制对象?
- 当(且仅当)对象具有复制构造函数时,如何复制对象?
- 我的程序运行良好,可以复制对象,但是当我使用复制分配(=)时,它仍然可以正常运行.为什么不给错误
- 如何复制对象
- 如何构造不可移动不可复制对象的元组?
- 不可复制对象数组的 consexpr 初始化?
- 提升::可选与标准::不可复制对象的可选
- 如何在C++中通过引用复制对象
- 从指针复制对象
- 删除浅表的复制对象和源对象
- 使用realloc可以安全地重新分配琐碎的可复制对象的存储吗
- C 返回复制对象
- 如何将智能指针作为类属性来复制对象
- 为什么在复制对象时忽略顶级常量
- std::shared_ptr 在复制对象时导致问题
- 安全复制对象的替代方案
- 当类包含boost::container::flat_set时,复制对象时出错