-1

对于 c 样式数组,会发生什么 float *fp1 = std::move(fp); 如下代码(1),和float *fp1 = fp; 一样吗?如下代码(2),我打印结果,似乎它们是相同的。一般来说,如果对象不可移动,std::move 什么也不做,对吧?

   int main(){
    float *fp = new float[20];
    //float *fp1 = std::move(fp); //(1)
    float *fp1 = fp; //(2)
    std::cout << "fp: " <<fp << " fp1: "<< fp1<< std::endl;
    unique_ptr<float> u_fp(fp);
    cout << "u_fp : "<< u_fp.get()<<endl;
    unique_ptr<float> u_fp1 = std::move(u_fp);

}
4

2 回答 2

3

With float *fp = new float[20];,fp不是数组,而是指向 20 个浮点对象数组的第一个元素的指针。您可以显示sizeof(fp)以确保。

指针确实是可移动类型,简单地移动或复制它是完全相同的操作。不可移动类型是禁止移动赋值的类型,要么通过明确删除移动赋值运算符,要么因为移动它会移动不可移动的子对象。尝试移动不可移动的对象将导致编译错误。

顺便说一句,如果您尝试移动一个真正的 C 数组,它将衰减为一个指针,并且与第一种情况相同:

float arr[20];
float *fp1 = std::move(arr);  // arr decays to a pointer so the same as fp1 = arr
于 2020-07-01T07:12:45.120 回答
1

一般来说,std::move如果对象不可移动,就什么也不做,对吧?

std::move只是对右值引用的强制转换,表示您可以丢失其参数中的值。由构造函数或赋值运算符来做一些特殊的事情。通常,您可以期望参数 ofstd::move在那之后处于有效但未定义的状态,因此执行其析构函数或重置它都应该没问题,但除了谁知道。

由于像指针这样的简单数据类型没有重载的构造函数或赋值运算符,因此强制转换在这里不起作用,并且您确实得到了一个简单的赋值。

我会使用术语“可移动类型”作为“可复制”的超集。任何可以复制的类型,您都可以通过复制它然后摆脱原件来移动。有些类型可以移动但不能复制;因为那些std::move是特别相关的。有些类型你甚至不能移动,它们会将构造函数标记为已删除或私有。cppreference同意声明可复制类型也是可移动的。

另请注意,许多容器类型是可复制的(如果它们的元素是),但复制它们比移动它们更昂贵。所以说这std::move仅与不可复制的可移动类型有关是错误的。

于 2020-07-01T07:26:32.117 回答