且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

将从函数返回的Rvalue分配给另一个Rvalue

更新时间:2022-10-18 13:53:03

函数调用表达式的值类别实际上是一个右值。



确实,您不能在右值基元上调用复制赋值运算符。实际上,C语言中右值的历史定义是区别在于它们可能不在集合的左侧。



类的赋值运算符有些不同,虽然。它们是常规的成员函数。而且没有规则可以阻止调用右值的成员函数。的确,当函数具有副作用时,它通常非常有用。手势,改变临时状态。声明之后,临时对象将被丢弃。没有UB,只有无意义的复制。这: Test&运算符=(测试)& =默认值; 。引用限定符仅在c ++ 11中稍后才添加,因此(隐式)副本分配不能指定为较早地具有引用限定符。据推测,C ++ 11并未更改隐式副本构造函数的限定符,以防止破坏确实分配给右值的旧代码,即使这种分配似乎毫无意义。 高完整性C ++编码Standard 建议您对用户定义的副本分配运算符使用ref限定符。


class Test {

public:

    int n1;

};

Test func() {

    return Test();

}

int main() {

    func() = Test();

}

This doesn't make sense to me. How and why is this allowed? Is it undefined behavior? If a function returns an rvalue, then how is it possible to set an rvalue to another rvalue? If I tried this with any primitive types, it would give me an error like I expect.

I know that lvalues are a place in memory, so is the function creating a temporary lvalue (rvalue?) and assigning it to another lvalue? Can someone explain how this syntax works?

The value category of the function call expression is in fact an rvalue.

Indeed, you may not call the copy assignment operator on rvalue primitives. The historical definition of rvalues in C was in fact the distinction that they may not be on the left side of an assigment.

The assignment operators of classes are a bit different, though. They're regular member functions. And no rule prevents calling member functions of rvalues. Indeed, it's often quite useful when the functions have side-effects.

How it works, well, the copy assignment operator is called on the temporary, the operator copies the right hand argument, changing the state of the temporary. After the statement, the temporary object is discarded. There is no UB, just pointless copying.

You can prevent calling copy assignment on an rvalue, by declaring the operator with a reference qualifier like this: Test& operator=(Test) & = default;. Ref-qualifiers were added only later in c++11, so (implicit) copy assignment couldn't have been specified to be ref-qualified earlier. Presumably, C++11 didn't change the qualifier of implicit copy constructor to prevent breaking old code that does assign to an rvalue, even though such assignment does seem quite pointless. The High Integrity C++ Coding Standard recommends that you do use ref qualifier with user defined copy assignment operators.