改变被引用成员的成员

时间:2014-04-26 08:18:51

标签: c++

当我运行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?

3 个答案:

答案 0 :(得分:3)

您的代码没有按照您的想法行事。引用不是“可重新安置的”#34;。一旦绑定,你就无法改变它所绑定的内容。

声明:

a.m=p;

不会a.m引用p。它将p复制到a.m(它保持与以前一样)。

请注意,Agg的构造函数使用非标准扩展名。您不能将非const l值引用绑定到标准C ++中的临时值 - 这将创建一个&#34;悬空引用&#34;因为临时在转让后被销毁。 const引用可以延长临时(but not always)的生命周期。

答案 1 :(得分:2)

当你写:

Agg():m(MyPOD())

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

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

BTW代码a.m=p;调用a.m.operator=(p),它不会“重新定位引用”或任何内容。

答案 2 :(得分:1)

将我的评论放到答案中:引用不能被反弹,并且它绑定在你的情况下的构造函数中。它们必须绑定在构造函数初始化列表中,至少是pre-c ++ 11,并且你在这里做了这个:

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

你似乎在后面工作的是一个基本上复制到已绑定变量的副本,它也会改变它引用的原始变量,但在你的情况下只是MyPOD()

顺便说一下,这是一个临时变量,所以即使它目前似乎工作正常,也不要使用它。无法保证继续工作。它实际上甚至没有用我的Archlinux上的gcc 4.9进行编译:

  

main.cpp:在构造函数'Agg :: Agg()'中:   main.cpp:12:19:错误:从'MyPOD'类型的右值开始无效初始化'MyPOD&amp;'类型的非const引用           AGG():M(MyPOD()){}

或clang版本3.4:

  

main.cpp:12:10:错误:非常量左值引用类型&#39; MyPOD&#39;不能绑定到临时类型的MyPOD&#39;      AGG():M(MyPOD()){}            ^ ~~~~~~~   生成1个错误。

这意味着您无法从临时(右值)设置非const引用。

因此,简而言之,您的评论在这里是错误的:

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

这将是正确的评论:

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