理解本例中的move构造函数行为

understand the move constructor behavior in this example

本文关键字:move 构造函数      更新时间:2023-10-16

我正在学习c++ 11中的移动语义。我写了一个小程序来测试移动语义的行为。但是它的表现不像我期望的那样,有人能解释一下为什么吗?

#include<iostream>
using namespace std;

class Vector
{
public:
    Vector()
    {
    cout << "empty Ctor"<<endl;
    array = new int[10];
    size = 10;
    }
    Vector(int n)
    {
    array = new int[n];
    size = n;
    for (int i=0; i<size; ++i)
        array[i] = i;
    cout << "Ctor"<<endl;
    }
    Vector(const Vector& v):size(v.size)
    {
    array = new int[size];
    for (int i=0; i<size; ++i)
        array[i] = v.array[i];
    cout << "copy"<<endl;
    }
    Vector(Vector&& v):size(v.size)
    {
    array = v.array;
    v.array = nullptr;
    cout << "move"<<endl;
    }
    ~Vector()
    {
    delete array;
    }
private:
    int* array;
    int size;
};
int main() {
    Vector v(10); //print Ctor. (as expected)
    Vector v1(std::move(v)); //print move. (as expected)
    Vector v2(*(new Vector(2)));  //print Ctor, copy. (I expect Ctor, move)
    Vector v3(Vector(2)); //print only Ctor. (I expect Ctor, move)
}

那么,为什么打印不是我所期望的。因为我认为传递给v2和v3的值都是右值。对于v3,为什么它只打印tor而不打印move或copy

Vector v2(*(new Vector(2)));

new Vector(2)是一个右值,但是对它解引用产生一个左值,因此是复制而不是移动。

Vector v3(Vector(2));

由于临时Vector是不必要的,编译器将省略该副本。您的编译器可能有一个禁用复制省略的标志,以便您可以看到额外的移动,例如GCC和Clang中的-fno-elide-constructors