赋值运算符不应该返回一个“空”实例?

Posted

技术标签:

【中文标题】赋值运算符不应该返回一个“空”实例?【英文标题】:Assignment operator is returning an "empty" instance when it shouldn't? 【发布时间】:2017-01-02 14:24:57 【问题描述】:

我正在实现一个堆栈只是为了练习。所以,总的来说,我有这样的东西:

Stack stack;
stack.push(element1;
stack.push(element2);

Stack copy;
copy = stack;

所以我重载了赋值运算符,因为我还想生成新的元素实例(而不仅仅是将每个元素的指针从一个复制到另一个),如下

Stack &Stack::operator=(const Stack &toCopy) 
    Stack* stack = new Stack;
    if (toCopy.first == NULL) return *stack;
    for (Node* actual = toCopy.first; actual != NULL; actual = actual->sig) 
        stack->push(actual->elem);
    
    // In this state, *stack has 2 elements as it should
    return *stack;

回到主体,复制变量没有得到更改...它仍然是空的,就好像分配从未发生过一样。好像我刚刚做了Stack copy;你能解释一下这里发生了什么吗?

【问题讨论】:

为什么投反对票? 听起来你对内存管理有一些基本的误解。您的operator= 泄漏内存(new Stack 永远不是deleted)。它也永远不会更新*this,而是更新新堆栈并且永远不会对新堆栈做任何事情。您的代码的其他部分可能有很多您没有发布的错误。以后发MCVE,如果你停止使用原始指针,生活会变得更轻松。 你应该修改operator=中的this,而不是返回一个新的堆栈。 您的 operator= 应该更改 this 并返回对 this 的引用,而不是创建新对象并返回它。 我现在明白了。谢谢大家! 【参考方案1】:

您没有修改当前对象(即*this)。

您只是通过new 创建了一个新对象,然后将其返回。注意copy = stack;,它等同于copy.operator=(stack);,注意返回的值没有被使用,它只是被丢弃(并导致内存泄漏),copy没有改变。

你应该这样做:

Stack &Stack::operator=(const Stack &toCopy) 

    // do some work to clear current elements in *this
    // ...

    // add elements from toCopy
    for (Node* actual = toCopy.first; actual != NULL; actual = actual->sig) 
        this->push(actual->elem);
    

    // operator= is supposed to return *this in general
    return *this;

【讨论】:

【参考方案2】:

您可能误解了赋值运算符。它在等号左侧的对象的上下文中工作。因此,您的 ::operator=(...) 应该始终在 *this 上工作,并且应该始终返回 *this

您发布的operator=(...) 正在对您在堆上分配的 Stack 对象进行操作,并且您正在对it 而不是@987654325 进行操作@。

您可以在代码中有效地将stack 替换为this。即:

Stack &Stack::operator=(const Stack &toCopy) 
    //Stack* stack = new Stack; // Don't do this.
    if (toCopy.first == NULL) return *this;
    for (Node* actual = toCopy.first; actual != NULL; actual = actual->sig) 
        this->push(actual->elem); // You could also just call push without "this->"
    
    // In this state, *stack has 2 elements as it should
    return *this;

【讨论】:

以上是关于赋值运算符不应该返回一个“空”实例?的主要内容,如果未能解决你的问题,请参考以下文章

赋值运算符 String 对象

C#语法糖空合并运算符??和空合并赋值运算符 ??=

为啥移动赋值运算符应该返回对 *this 的引用 [重复]

C++ 为啥赋值运算符应该返回一个 const ref 以避免 (a=b)=c

来自'??' 的 C# 类型推断(“var”)赋值空合并运算符

python运算符