正在更改引用成员的成员
Altering member of referenced member
当我运行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
- 非静态成员引用必须相对于特定对象
- 在C++中,如果成员引用在其声明中初始化,为什么需要存储空间?
- 成员引用基类型 'char' 不是 C++ 中的结构或联合
- 成员引用基类型不是结构或联合
- for 循环说 - 错误 成员引用基类型"int [13]"不是结构或联合
- 成员引用基类型 'double [10]' 不是结构或联合
- 使用默认值初始化成员引用
- 错误:成员引用基类型"uint32_t"(也称为"无符号 INT")不是结构或联合
- 无法用2D矢量成员引用对象
- 是否可以在同一对象中对成员 std::shared_ptr 进行成员引用<variable>?
- 是否有一种方法可以将C 类成员引用到向量而不明确添加它们
- C++:成员引用还是指针
- C++非静态成员引用
- C++ 成员引用基类型'int'不是结构或联合
- 将成员引用变量置于成员指针变量之上的原因
- C++非静态成员引用必须相对于特定对象
- 无法理解错误 msg:"非静态成员引用必须相对于特定对象"
- 返回类成员引用变量会导致运行时错误
- 可以安全地将移动的对象存储在成员引用中
- 成员引用基类型'double'不是结构或联合