将此指针按值分配给 getter 的 return 值是什么意思?

What is the meaning of assigning to return value of getter taking this pointer by value?

当我跳到现有代码并错误地使用 getter 设置 属性,

时,我产生了这个疑问
obj.getProp() = otherProp;

而不是调用 setter,

obj.setProp(otherProp);

我没有意识到错误,因为编译和运行时都没有错误;作业导致无操作。

所以我想出了下面的例子,它输出 337:

#include <iostream>

struct A {
    int x = 0;
    A(int x) : x(x) {}
    A(A& a) : x(a.x) {}
    void operator=(A const& other) { x = other.x; }
};

struct B {
    A a{3};
    int x{3};
    A  getAbyVal() { return a; }
    A& getAbyRef() { return a; }
    int getXbyVal() { return x; }
};

int main() {
    B b;
    std::cout << b.a.x;   // this and the other two cout print what I expect, but...
    b.getAbyVal() = A{7}; // ... I expected this to fail at compilation time in the first place...
    //b.getXbyVal() = 3;  // ... just like this fails.
    std::cout << b.a.x;
    b.getAbyRef() = A{7};
    std::cout << b.a.x;

}

所以我的问题有两个方面:

what in b.getAbyVal() = A{7}; is different from b.getXbyVal() = 3; so that the former compiles and the latter doesn't (beside the fact that the types are A and int)?

区别恰恰是一个函数returns一个class类型,另一个函数returns一个POD类型。临时 int,例如不能分配给:

42 = x; // error

类似地,该语言也不允许分配给从函数返回的临时 int。这不是 user-defined class 类型的默认行为,因此分配给临时 A 编译:

A{} = x; // ok

changing void operator=(A const& other) { x = other.x; } to void operator=(A const& other) & { x = other.x; } makes b.getAbyVal() = A{7}; fail to compile. Why is this the case?

在末尾添加一个&称为ref-qualifier,并允许user-definedclass在出现时具有与POD类型相同的语义分配给一个临时的。在 operator= 末尾添加 & 将其限制为仅用于 l-value (基本上,命名变量或从函数返回的引用)。

A{} = x;  // now error
A a;
a = x;    // still ok

what in b.getAbyVal() = A{7}; is different from b.getXbyVal() = 3; so that the former compiles and the latter doesn't (beside the fact that the types are A and int)?

令人惊讶的是,类型的差异正是导致一个编译正确而另一个编译失败的原因。

A 为其定义了一个赋值运算符,因此编译器尽职尽责地在 return 值上调用它(只是为了稍后丢弃整个对象)。但是您编写的代码支持这一点。从编译器的角度来看,尽管对象将被根除(副作用 在正式的说法中),您的赋值运算符中可能还发生了一些其他有趣的事情。

int 作为 return 值,编译器 知道 将值赋给 int 没有副作用,因此将任何值赋给对象立即根除没有任何意义。