【问题标题】:what will happen when std::move with c style array or not movable object当 std::move 使用 c 样式数组或不可移动对象时会发生什么
【发布时间】:2020-10-18 10:56:09
【问题描述】:

对于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);

}

【问题讨论】:

    标签: c++ unique-ptr stdmove


    【解决方案1】:

    对于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
    

    【讨论】:

      【解决方案2】:

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

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

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

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

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

      【讨论】:

        猜你喜欢
        • 2014-12-31
        • 2015-09-06
        • 1970-01-01
        • 2014-09-29
        • 2020-10-19
        • 2018-06-08
        • 2019-04-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多