C++ C++;函数返回一个右值,但可以为其分配一个新值吗?

C++ C++;函数返回一个右值,但可以为其分配一个新值吗?,c++,assignment-operator,temporary,rvalue,C++,Assignment Operator,Temporary,Rvalue,代码如下: #include <iostream> using namespace std; class A { }; A rtByValue() { return A(); } void passByRef(A &aRef) { // do nothing } int main() { A aa; rtByValue() = aa; // compile without errors pass

代码如下:

 #include <iostream>
 using namespace std;

 class A {

 };

 A rtByValue() {
return A();
 }

 void passByRef(A &aRef) {
    // do nothing
 }

 int main() {
    A aa;
    rtByValue() = aa;            // compile without errors
    passByRef(rtByValue());      // compile with error 

    return 0;
 }

它说我不能将一个右值作为一个非常量引用的参数来传递,但我所困惑的是为什么我可以分配给这个右值,正如代码所示。

@ddriver正如我所期望的那样,这个输出数字7

#include <iostream>
 using namespace std;

 class A {
 public:
     int i;
     A() {i = 0x07;}
 };

 A rtByValue() {
return A();
 }

 void passByRef(A &aRef) {
     cout << aRef.i;
 }

 int main() {
    passByRef(rtByValue());
    return 0;
 }
#包括
使用名称空间std;
甲级{
公众:
int i;
A(){i=0x07;}
};
一个rtByValue(){
返回A();
}
无效密码引用(A&aRef){

cout传递右值
rtByValue()
对于期望左值引用的函数不起作用,因为这需要从右值初始化左值引用参数。§8.5.3/5描述了如何初始化左值引用–我不会完全引用它,但它基本上说可以初始化左值引用

  • 或者来自另一个左值引用
  • 或者可以转换为中间类型的左值引用的东西
  • 或者从右值,但仅当我们初始化的左值引用是常量引用时
因为我们需要初始化的参数不是常量引用,所以这些都不适用

另一方面,

rtByValue() = aa; 
i、 例如,分配给临时对象是可能的,因为:

(§3.10/5)修改对象需要对象的左值,但在某些情况下,类类型的右值也可用于修改其引用对象。[示例:为对象(9.3)调用的成员函数可以修改对象。-结束示例]

因此,这仅仅是因为
A
属于类类型,并且(隐式定义的)赋值运算符是成员函数(有关详细信息,请参阅)

<> >(如果<代码> RTByValueAudio()/Case>将返回,例如,<代码> int <代码>,则赋值将不起作用)

,因为您可以(但不应该!)重写运算符=,这样在rValk上调用它是有意义的。请考虑下面的代码:

#include<iostream>

using namespace std;

class foo;

foo* gotAssigned = NULL;
int assignedto = -1;

class foo {
public:
  foo(int v) : val(v) {}
  foo& operator=(int v) {
    assignedto=v;
    gotAssigned = this;
    val = v;
    return *this;
  }
  int val;
};

foo theFoo(2);

foo returnTheFooByValue() {
  return theFoo;
}

main() {
  returnTheFooByValue()=5;
  cout << "[" << assignedto << "] " << theFoo.val << " versus " << gotAssigned->val << endl;
}
我不能保证你会看到同样的结果

正如您所看到的,分配是会发生的,但是任何使用已分配对象的尝试都会导致特定于实现的行为

顺便提一下,这仅适用于用户定义的类型。此代码:

int v(){
  return 2;
}

main(){
  v()=4;
}

不编译。

是的,非常量引用无法绑定到临时变量。奇怪。我可以在MS VS 2010中编译并运行它。@克里斯,但为什么我可以分配给它。我可以分配给它,为什么我不能将它作为引用传递?你在使用什么编译器?@0x499602D2他使用g++而我是VS 2010,只是因为你得到了值并不意味着它不是未定义的havior。我一直在从属于同一类别的数组的越界索引中获取正确的值。我认为标准不允许这样做,MS可能对此有不同的看法,就像他们在许多其他方面一样。我不明白为什么它不起作用。类A的实际实例正在生成,并且在传递被引用时仍然存在在C++的代码> PASBYRFF <代码>函数中,我没有问题要分配给< C++ >代码>。这是VisualC++中一个众所周知的编译器错误,它可能永远不会被修复。它是一个错误,因为标准要求编译器生成诊断,Visual C++不。你会怎么处理它?将其设置为常量引用可以很好地工作,如果需要修改它,则始终可以按值或右值引用进行修改。修改原始对象是毫无意义的,因为原始对象是将要销毁的临时对象。它不是特定于实现的,是未定义的行为。您正在访问已销毁的临时对象。
$ g++ -O0 -o rveq rveq.cc && ./rveq
[5] 2 versus 5
$ g++ -O1 -o rveq rveq.cc && ./rveq
[5] 2 versus 2
$ g++ -O4 -o rveq rveq.cc && ./rveq
[5] 2 versus -1218482176
int v(){
  return 2;
}

main(){
  v()=4;
}