正在更改引用成员的成员

Altering member of referenced member

本文关键字:成员 引用      更新时间:2023-10-16

当我运行testRef()时,如果c++引用真的是对内存中同一点的引用,则结果与我预期的不同:

struct MyPOD{
   float x;
};
struct Agg{
   MyPOD& m;
   Agg():m(MyPOD()){}
};
void testRef(){
    MyPOD p;
    p.x=15.5;
    Agg a;
    a.m=p; //referencing the object above
    qDebug()<<"a.m.x is: "<<a.m.x; //15.5
    qDebug()<<"p.x is: "<<p.x; //15.5
    a.m.x=5;
    qDebug()<<"a.m.x is: "<<a.m.x; //5
    qDebug()<<"p.x is: "<<p.x; //15.5
}

我的问题是:如果a.m确实是指p,为什么改变a.m.x不能同时改变p.x?

您的代码不会按照您的想法执行。引用不是"可重新就座"。一旦它被绑定,你就无法更改它绑定的内容。

声明:

a.m=p;

不使CCD_ 2参考CCD_。它将p复制到a.m中(与以前一样保持绑定)。

请注意,Agg的构造函数使用了非标准扩展。在标准C++中,不能将非常常量的l值引用绑定到临时引用,因为临时引用在赋值后立即被销毁,所以会创建"悬空引用"。const引用可以延长临时的生存期(但并非总是如此)。

编写时:

Agg():m(MyPOD())

这应该无法编译,因为MyPOD()是一个临时对象,临时对象不能绑定到非常量引用。

如果你的编译器允许,那么谁知道发生了什么,你就进入了编译器扩展的领域。也许它允许这个代码,但当您稍后访问m时,行为是未定义的,并且它引用了一个已被破坏的对象。

顺便说一下,代码a.m=p;调用a.m.operator=(p),它不会"重新放置引用"或其他任何东西。

将我的注释放入一个答案中:引用不能反弹,在您的情况下,它被绑定在构造函数中。它们必须绑定在构造函数初始值设定项列表中,至少在c++11之前是这样,而您在这里这样做:

Agg():m(MyPOD()){}
      ^^^^^^^^^^

您稍后要做的是基本上复制到已经绑定的变量中,这也会更改它所引用的原始变量,但在您的情况下,这只是MyPOD()

顺便说一句,这是一个临时变量,所以即使它目前看起来工作正常,也不要使用它。不能保证它能继续工作。事实上,它甚至没有在我的Archlinux上使用gcc 4.9进行编译,给出的是:

main.cpp:在构造函数"Agg::Agg()"中:main.cpp:12:19:错误:"MyPOD&"类型的非常量引用的初始化无效来自"MyPOD"类型的右值Agg():m(MyPOD()){}

或clang版本3.4:

main.cpp:12:10:错误:对类型"MyPOD"的非常量左值引用无法绑定到类型"MyPOD"的临时值Agg():m(MyPOD()){}^~~~~~~~生成1个错误。

这意味着您不能从临时(右值)设置非常量引用。

总之,你的评论是错误的:

Agg a;
a.m=p; //referencing the object above

这将是恰当的评论:

Agg a;
a.m=p; //copying the object above by using the assignment operator