移动链接到构造函数的方法的语义
Move semantics of a method chained to a constructor
我是 C++ 新手,正在尝试掌握移动语义。以下代码是我编写的准系统结构。无论如何,它都不是软件工程的最佳示例,但仅供学习之用。它拥有一个资源,删除了复制构造函数和复制赋值运算符,定义了一个移动构造函数和一个移动赋值运算符,有一个析构函数,并且有一个应该 return 原始对象的方法:
struct HasAResource
{
int* arr;
HasAResource(int size):
arr(new int [size])
{}
HasAResource(const HasAResource& other) = delete;
HasAResource& operator=(const HasAResource& other) = delete;
HasAResource(HasAResource&& other):
arr(nullptr)
{
arr = other.arr;
other.arr = nullptr;
}
HasAResource& operator=(HasAResource&& other)
{
if (this != &other)
{
delete[] arr;
arr = other.arr;
other.arr = nullptr;
}
return *this;
}
~HasAResource() { delete[] arr; }
HasAResource& doStuff()
{
return *this;
}
};
int main(int argc, char const *argv[])
{
HasAResource x = HasAResource(42).doStuff();
return 0;
}
在主函数中,我试图构造一个对象并立即调用它的方法。我的目标是修改我构建的临时对象,然后他们将其移动到 x
而不制作任何副本(这样资源只有一个所有者)。但是,编译器给我一个与删除的复制构造函数相关的错误。这意味着尽管我尽了最大努力,它仍在尝试制作副本。
我的问题是:
- 这里到底发生了什么?新对象在哪里是右值或左值,为什么?
- 如果可能,我如何修改此程序以实现所需的行为?
再次强调,我的目标是了解语言在做什么,而不是最佳软件工程实践(比如使用std::unique_ptr
)。
My goal was to modify the temporary object I constructed and them move it to x
without making any copies
doStuff()
不会 return 成为 临时 ,因此 x
没有可移动的右值。由于 doStuff()
的 return 值不是右值,编译器无法调用 x
的移动构造函数,因此它尝试调用复制构造函数并因此失败的原因是那就是delete
。
在这种情况下,您将需要使用 std::move()
显式将 returned 引用转换为右值,然后移动构造函数将按预期调用:
HasAResource x = std::move(HasAResource(42).doStuff());
否则,按值将doStuff()
更改为return一个新对象,并让编译器使用copy elision为您优化临时对象,例如:
static HasAResource doStuff(int size)
{
HasAResource x(size);
x.doStuff();
return x;
}
HasAResource x = HasAResource::doStuff(42);
我是 C++ 新手,正在尝试掌握移动语义。以下代码是我编写的准系统结构。无论如何,它都不是软件工程的最佳示例,但仅供学习之用。它拥有一个资源,删除了复制构造函数和复制赋值运算符,定义了一个移动构造函数和一个移动赋值运算符,有一个析构函数,并且有一个应该 return 原始对象的方法:
struct HasAResource
{
int* arr;
HasAResource(int size):
arr(new int [size])
{}
HasAResource(const HasAResource& other) = delete;
HasAResource& operator=(const HasAResource& other) = delete;
HasAResource(HasAResource&& other):
arr(nullptr)
{
arr = other.arr;
other.arr = nullptr;
}
HasAResource& operator=(HasAResource&& other)
{
if (this != &other)
{
delete[] arr;
arr = other.arr;
other.arr = nullptr;
}
return *this;
}
~HasAResource() { delete[] arr; }
HasAResource& doStuff()
{
return *this;
}
};
int main(int argc, char const *argv[])
{
HasAResource x = HasAResource(42).doStuff();
return 0;
}
在主函数中,我试图构造一个对象并立即调用它的方法。我的目标是修改我构建的临时对象,然后他们将其移动到 x
而不制作任何副本(这样资源只有一个所有者)。但是,编译器给我一个与删除的复制构造函数相关的错误。这意味着尽管我尽了最大努力,它仍在尝试制作副本。
我的问题是:
- 这里到底发生了什么?新对象在哪里是右值或左值,为什么?
- 如果可能,我如何修改此程序以实现所需的行为?
再次强调,我的目标是了解语言在做什么,而不是最佳软件工程实践(比如使用std::unique_ptr
)。
My goal was to modify the temporary object I constructed and them move it to
x
without making any copies
doStuff()
不会 return 成为 临时 ,因此 x
没有可移动的右值。由于 doStuff()
的 return 值不是右值,编译器无法调用 x
的移动构造函数,因此它尝试调用复制构造函数并因此失败的原因是那就是delete
。
在这种情况下,您将需要使用 std::move()
显式将 returned 引用转换为右值,然后移动构造函数将按预期调用:
HasAResource x = std::move(HasAResource(42).doStuff());
否则,按值将doStuff()
更改为return一个新对象,并让编译器使用copy elision为您优化临时对象,例如:
static HasAResource doStuff(int size)
{
HasAResource x(size);
x.doStuff();
return x;
}
HasAResource x = HasAResource::doStuff(42);