移动赋值运算符未被调用

4

我刚刚在进行移动语义方面的练习,但似乎无法弄清为什么我的移动赋值运算符没有被调用。

以下是我的类(请忽略与问题无关的任何不良实践):

private:
    int sz;
    double* elems;

public:
    Vector(int size):sz(size), elems(new double[size])
    {
         for(int i=0; i!=sz; ++i)
         {
             elems[i] = i;
         }
    }

    ~Vector()
    {
         std::cout << "Destruct " << std::endl; delete [] elems;
    }

    double& operator[](int i)
    {
        return elems[i];
    }
    const double& operator[](int i)const 
    {
         return elems[i];
    }

    //operator+ to add vectors
    friend Vector operator+(const Vector& a, const Vector& b)
    {

        Vector ret(a.sz);
        if(a.sz!=b.sz)
            return 0;
        std::cout << "Adding" << std::endl;
        for(int i=0; i!=a.sz; ++i)
        {
            ret[i] = a[i] + b[i];
        }

        return ret;
     }

     //move constructor
     Vector(Vector&& a): sz(a.sz),elems(a.elems)
     {
          std::cout << "Move constructor"<< std::endl;
          a.elems = nullptr;
          a.sz = 0;
     }

     //move assignment
     Vector& operator=(Vector&& a)
     {
        std::cout << "Moveeee" << std::endl;
        delete [] elems;
        elems = a.elems;
        sz = a.sz;
        a.elems = nullptr;
        a.sz = 0;

        return *this;
     }

现在我的测试用例如下:

Vector v1(3);
Vector v2(3);
Vector v3(3);
Vector v4 = v1+v2;

输出如下:
Adding
Move constructor
Destruct
Destruct
Destruct
Destruct
Destruct

我希望的是当执行 Vector v4 = v1+v2; 时调用 move 赋值函数,但实际上却没有。相反地,它调用了 move 构造函数。
我甚至尝试过 Vector v4 = std::move(v2);,但也不起作用,并且调用了 move 构造函数。
有任何想法为什么没有调用 move 赋值函数吗?

1
这基本上是编译器的优化。只有在对象构造完成后才会调用赋值运算符。如果你执行 Vector v4; v4 = v1 + v2;,那么应该会调用赋值运算符。 - leetNightshade
2
在你开始学习C++11之前,你应该先了解什么是赋值 -- 你的代码中没有任何赋值!相反,你有复制初始化。 - Kerrek SB
1
@leetNightshade:这不是一种优化。这完全是一个不同的结构。 - Kerrek SB
@Kerrek SB,你知道这个结构体叫什么吗? - leetNightshade
1
@leetNightshade:是的,它被称为“复制初始化”。 - Kerrek SB
@KerrekSB 对不起,你是对的,我完全忘记了复制初始化,不知道为什么。 - Kakalokia
1个回答

9

从语义上来说,你并没有调用赋值操作。

Vector v4 = v1+v2;

真正的含义是:

Vector v4(v1+v2);

如果没有复制构造函数,但存在默认构造函数和可接受的赋值函数,则将调用赋值函数。如注释所述,您需要执行以下操作:
Vector v4; v4 = v1 + v2;

拥有真正的任务分配


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接