我可以将 std::move 与不提供 move 构造函数的类一起使用吗?

can I use std::move with class that doesn't provide a move constructor?

本文关键字:move 一起 std 我可以 构造函数      更新时间:2023-10-16

我有这样的类:

class myClass
{
int x[1000];
public:
int &getx(int i)
{
return x[i];
}
}

请注意,我在这里没有提供移动结构。

如果我使用以下代码:

myClass A;
auto B=std::move(a);

A是移动到 B 还是因为我没有提供移动构造函数,A 被复制到 B?

对象是否有任何默认的移动构造函数?如果是,它如何与指针和动态分配的数组一起工作?

虽然您没有提供显式移动构造函数,但编译器为您提供了隐式移动构造函数。

如果类 X 的定义没有显式声明移动构造函数,则当且仅当

  • X 没有用户声明的复制构造函数,并且
  • X 没有用户声明的复制赋值运算符,
  • X 没有用户声明的移动分配运算符,
  • X 没有用户声明的析构函数,并且
  • 移动构造函数不会隐式定义为已删除。

所以你的问题的答案是:不,A 没有复制到 B。

不清楚您在其他问题中问了什么。请具体说明更多详细信息。

对象是否有任何默认的移动构造函数?

是的,在您的情况下。对于任何类型T,移动构造函数只有在满足某些条件时才隐式声明。更多细节可以在 cpperference.com 看到。

如果是,它如何与指针和动态分配的数组一起工作?

默认实现将创建指针的浅拷贝。因此,多个对象将指向动态分配的数组。这将导致问题。有关该主题的更多信息,请参阅三人法则。

如果您有指向动态分配数组的指针,则需要:

  1. 提供一个显式定义的复制构造函数,该构造函数对动态分配的数组执行正确的操作。这样做的副作用是默认的移动构造函数将被隐式删除。和/或
  2. 提供一个显式定义的移动构造函数,您可以在其中适当地移动动态分配数组的所有权。

移动构造函数是为类生成的,因为您没有定义任何避免生成它的方法(作为用户定义的析构函数或复制构造函数(

自动生成的移动构造函数将移动每个成员。对于int[1000]它等同于复制。

如果没有为类类型(结构、类或联合(提供用户定义的移动构造函数,并且满足以下所有条件:

  • 没有用户声明的复制构造函数。
  • 没有用户声明的复制分配运算符。
  • 没有用户声明的移动分配运算符。
  • 没有用户声明的析构函数

然后编译器将移动构造函数声明为其类的非显式内联公共成员,签名为 T::T(T&&(。

引用自 cpp首选项

基本上,是的,只要您不定义复制构造函数、复制赋值重载、移动赋值重载或析构函数,就会创建默认移动构造函数。否则,您必须自己定义行为或使用: class_name ( class_name && ) = default; 这将显式声明移动构造函数的默认版本。

你的问题与此类似。请注意,std::move 只是一个强制转换。您的值a将被强制转换为右值引用,但在您的情况下,原始对象不会被掠夺或窃取。

要正确使用 API 或习语,您必须将其用于正确的事情。例如.class对于在堆上分配了大量对象数据的对象,移动最有意义。这样的物体很容易被偷走,"移动"可以使被偷的物体处于明确定义的状态。例如,规范示例可以是堆上带有字符串数据的某种类型的字符串类。

就您而言,您希望发生什么?假设 a是某个函数中的本地变量,即假设a在堆栈上。假设b是全局或文件范围或匿名命名空间变量,即不在堆栈上。从a移动到b时您希望发生什么?

对于一根绳子,偷窃是有意义的。就您而言,盗窃是荒谬的。