如果我正确地解释C++引用,它们就像指针一样,但保证数据完整性(没有NULL,没有(int*)0x12345).但是当引用对象的范围被遗漏时会发生什么?如果没有涉及魔法(可能不是),引用的对象将在我背后被摧毁.
我写了一段代码来检查:
#include <iostream>
using namespace std;
class A {
public:
A(int k) { _k = k; };
int get() { return _k; };
int _k;
};
class B {
public:
B(A& a) : _a(a) {}
void b() { cout << _a.get(); }
A& _a;
};
B* f() {
A a(10);
return new B(a);
}
int main() {
f()->b();
}
Run Code Online (Sandbox Code Playgroud)
该_k实例变量放入检查堆栈帧的存在.
令人惊讶的是,它不是段错误而是正确地打印'10',而我认为它A是在堆栈上分配的,并且堆栈帧f()将被至少cout<<调用覆盖.
Eva*_*ran 29
这是未定义的行为,你只是幸运的是,内存a还没有被用于其他任何东西.在更复杂的情况下,你几乎肯定会得到垃圾.在我的机器上,我使用此代码获得随机垃圾.对我来说,这可能是因为我使用的是64位机器,它使用寄存器调用约定.寄存器比主存储器更频繁地重复使用(理想情况下......).
那么回答你的"发生了什么"的问题.那么在这种情况下,引用可能只是一个有限指针和更友好的语法:-).在引擎盖下a存储地址.稍后该a对象超出范围,但B对象对该对象的引用a将不会"自动神奇地"更新以反映这一点.因此,您现在有一个无效的引用.
使用这个无效的引用几乎可以产生任何东西,有时候会崩溃,有时只会产生双层数据.
编辑:感谢Omnifarious,我一直在想这个.c ++中有一条规则,基本上说如果你有一个临时的const引用,那么临时的生命周期至少和const引用一样长.这引入了一个新问题.
编辑:移动到感兴趣的人的单独问题(const引用临时奇怪)
在C++语言中,引用所绑定的对象的生命周期与引用本身的生命周期没有任何关系,只有一个例外(见下文).
如果在引用之前销毁对象,则引用变为无效(如悬挂指针).任何访问该引用的尝试都会导致未定义的行为.这是您的示例中发生的情况.
引用在对象之前结束它的生命周期,然后......好吧,没有任何反应.引用消失,对象继续存在.
我上面讨论的唯一例外是使用直接临时对象初始化const引用.在这种情况下,临时对象的生命周期与引用的生命周期相关联.当参考死亡时,对象随之死亡
{
const std::string& str = "Hello!";
// A temporary `std::string` object is created here...
...
// ... and it lives as long as the reference lives
...
} // ... and it dies here, together with the reference
Run Code Online (Sandbox Code Playgroud)
PS您正在使用术语范围错误.范围是标识符的可见区域.范围本身与对象生命周期无关.当某些东西"留下范围"时,一般情况下某些东西不会被破坏.使用"叶子范围"措辞来指代对象的破坏点是一种流行的误解.