简体   繁体   English

将这个指针按值赋值给getter的返回值是什么意思?

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

This doubt came to me when I jumped on an existing code and mistakenly used a getter to set a property,当我跳入现有代码并错误地使用 getter 设置属性时,我产生了这个疑问,

obj.getProp() = otherProp;

instead of calling the setter,而不是调用setter,

obj.setProp(otherProp);

I did not realize the mistake because there was no error at compilation or runtime;我没有意识到错误,因为编译或运行时没有错误; the assignment resulted in a no-op.该任务导致无操作。

So I came up with the following example, which outputs 337 :所以我想出了下面的例子,它输出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;

}

So my question is two folds:所以我的问题是两个方面:

  • what in b.getAbyVal() = A{7}; b.getAbyVal() = A{7}; is different from b.getXbyVal() = 3;不同于b.getXbyVal() = 3; so that the former compiles and the latter doesn't (beside the fact that the types are A and int )?以便前者编译而后者不编译(除了类型是Aint的事实)?
  • changing void operator=(A const& other) { x = other.x; }改变void operator=(A const& other) { x = other.x; } void operator=(A const& other) { x = other.x; } to void operator=(A const& other) & { x = other.x; } void operator=(A const& other) { x = other.x; } to void operator=(A const& other) & { x = other.x; } void operator=(A const& other) & { x = other.x; } makes b.getAbyVal() = A{7}; void operator=(A const& other) & { x = other.x; }使b.getAbyVal() = A{7}; fail to compile.编译失败。 Why is this the case?为什么会这样?

what in b.getAbyVal() = A{7}; b.getAbyVal() = A{7}; is different from b.getXbyVal() = 3;不同于b.getXbyVal() = 3; so that the former compiles and the latter doesn't (beside the fact that the types are A and int )?以便前者编译而后者不编译(除了类型是Aint的事实)?

The difference is precisely that one functions returns a class type, and the other function returns a POD type.区别恰恰在于一个函数返回 class 类型,而另一个 function 返回 POD 类型。 A temporary int , for example can't be assigned to:例如,临时int不能分配给:

42 = x; // error

so similarly the language disallows assigning to a temporary int returned from a function as well.所以类似地,该语言也不允许分配给从 function 返回的临时int This is not the default behavior for user-defined class types so assigning to a temporary A compiles:这不是用户定义的 class 类型的默认行为,因此分配给临时A编译:

A{} = x; // ok

changing void operator=(A const& other) { x = other.x; }改变void operator=(A const& other) { x = other.x; } void operator=(A const& other) { x = other.x; } to void operator=(A const& other) & { x = other.x; } void operator=(A const& other) { x = other.x; } to void operator=(A const& other) & { x = other.x; } void operator=(A const& other) & { x = other.x; } makes b.getAbyVal() = A{7}; void operator=(A const& other) & { x = other.x; }使b.getAbyVal() = A{7}; fail to compile.编译失败。 Why is this the case?为什么会这样?

Adding a & at the end of is called a ref-qualifier, and allows a user-defined class to have the same semantics as a POD type when it comes to assigning to a temporary.在末尾添加&称为引用限定符,并允许用户定义的 class 在分配给临时对象时具有与 POD 类型相同的语义。 Adding a & at the end of operator= constrains it to only be used on an l-value (basically, a named variable, or a reference returned from a function).operator=的末尾添加&将其限制为仅用于左值(基本上,命名变量或从函数返回的引用)。

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

what in b.getAbyVal() = A{7}; b.getAbyVal() = A{7}; is different from b.getXbyVal() = 3;不同于 b.getXbyVal() = 3; so that the former compiles and the latter doesn't (beside the fact that the types are A and int)?以便前者编译而后者不编译(除了类型是 A 和 int 的事实)?

Surprisingly, the difference in types is exactly what makes one compile correctly, and other to fail.令人惊讶的是,类型的差异正是使一个编译正确而另一个编译失败的原因。

A has an assignment operator defined for it, so compiler dutifully invokes it on the return value (only to discard the whole object later). A为其定义了一个赋值运算符,因此编译器尽职尽责地在返回值上调用它(只是为了稍后丢弃整个 object)。 But the code you wrote supports this.但是您编写的代码支持这一点。 From the compiler view, some other interesting things might have happened in your assignment operator, despite the fact that the object will be eradicated ( side effects in formal parlance).从编译器的角度来看,尽管 object 将被根除(正式用语中的副作用),但您的赋值运算符中可能还发生了一些其他有趣的事情。

With int as a return value, compiler knows there are no side effects of assigning value to int, so assigning any value to object which is to be eradicated immediately does not make any sense.使用int作为返回值,编译器知道给 int 赋值没有副作用,所以给 object 赋值任何要立即根除的值都没有任何意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM