一个类的 = 运算符重载

3

最近我在复习C++中的运算符重载,按照建议为“=”的运算符重载返回*this的引用。但是随后我发现了一个问题:

#include <iostream>
using namespace std;

class MyClass
{
    int num = 4;
    public:
        MyClass() = default;
        MyClass(int x) : num(x) {}
        void getnum(int x)
        {
            num = x;
        }
        void shownum()
        {
            cout << num << '\n';
        }
        MyClass& operator = (const MyClass& obj)  // works even without const
        {
            this->num = obj.num;
            return *this;
        }
        ~MyClass() = default;
};

int main()
{
    MyClass x, y(5), z(7);

    z = MyClass(8) = y;   // temporary object return reference

    x.shownum();
    y.shownum();
    z.shownum();
}

尽管涉及到一个临时对象MyClass(8),该代码不会导致UB,之后将其与y相等(没有问题),但然后它的引用将被发送以与z相等。为什么这里不会出现悬挂引用问题?为什么重载函数可以在临时对象MyClass(8)上工作而不需要const MyClass&'


1
这是隐式转换中的一种。将对象更多地设置为const volatile是完全合法的。 - Incomputable
你为什么考虑编写这样的代码? - Ed Heal
实验 @EdHeal :-P - Ankit Acharya
不存在“将结果转换为... UB”的说法;未定义行为是源代码的属性,它仅意味着语言定义不告诉您使用此类代码的程序应该做什么。这并不意味着一定会发生什么不好的事情。(还要注意,在问题的代码中没有未定义的行为) - Pete Becker
2个回答

4

临时变量存在于完整表达式的结束。最后,临时变量会消失,由于此时所有的赋值已经完成,并且您没有将引用存储在任何地方,所以临时变量消失是可以接受的。


@OlzhasZhumabek 他们做。 - Ankit Acharya
@Joachim MyClass(8) 返回对自身的引用,但我的问题是,当它被使用后立即被销毁时,发送给z的引用现在是否无效,因为临时对象已被销毁。 - Ankit Acharya
@JoachimPileborg,没事了。我从gotw得到了所有我需要的答案 :) - Incomputable
@AnkitAcharya 不行,因为生命周期一直持续到完整的表达式结束。也就是在所有两个赋值完成之后。 - Some programmer dude
@JoachimPileborg,根据您的说法,只有在整个z = MyClass(8) = y表达式被评估之后,MyClass(8)才会被销毁? - Ankit Acharya
1
@AnkitAcharya 是的,就是这样。 - Some programmer dude

4
第一个任务 MyClass(8) = y; 返回一个MyClass&,但并未说明其为临时对象。因此它与下一个 operator= 的参数匹配,无论该参数是否要求const或non-const。
如果您尝试仅赋值临时对象 z = MyClass(8);,则会发现现在需要参数为const reference。
另外,在这里没有悬空引用,因为临时对象存在于完整表达式的末尾(通常在;处),而且没有指针或引用被保存在任何地方。只有 num 值的副本。

好的,这回答了第二个问题。那第一个问题呢? - Ankit Acharya
好的,一份价格两个问题。 :-) - Bo Persson

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