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