在搜索一些松散相关的东西时,我碰到了这句话:
引用可以比对象更长,并用于引用在同一地址创建的新对象。
来自answer。
现在,我一直都知道并且通过引用工作是不可变的,只需初始化一次即可。 阅读上面的引文,可能比我更有经验的人,让我想知道我是否错过了什么。
这句话是为了完整还是实际上不适用?
是否存在一些模式或情况,人们会经历在特定内存地址中登陆相同类型的新对象的痛苦,只是为了做一个切换器以供参考? (这对我来说似乎极其危险,更不用说在最好的时候了。)
答案 0 :(得分:3)
悬挂引用的问题与悬空指针的问题基本相同。
例如,两个函数
int &GetReference()
{
int x; // local variable
return x;
}
int *GetPointer()
{
int x;
return &x;
}
如果使用了返回的引用,或者指针被取消引用,会导致调用者出现完全相同的问题。
int &r = GetReference();
int *p = GetPointer();
r = 52;
*p = 42;
两个赋值都表现出未定义的行为,因为就程序而言,名为x的变量(在两个函数中)不再存在。但是,代码可以使SEEM正常工作。
通过释放动态分配的内存(C中的free(),C ++中的operator delete)创建悬空引用或指针也会发生同样的情况。
如果其他代码(最终)使用该存储器(例如,表示另一个变量,以表示不相关的对象),则该引用或指针通常可以访问该存储器位置处的任何内容。这可能会给出价值变化的虚假问题(这可能会给使用引用的代码或发现变量或对象被更改的无关代码带来惊喜。)
实际上并不是渴望或使用它。这是一个危险的程序缺陷,通常很难修复或调试 - 因为它为两个完全不相关的代码段提供了一条路径来影响另一个代码使用的数据。
幸运的是,现代编译器通常(如果配置为提供最大警告级别)会对许多可疑构造发出警告(例如,返回指针或对局部变量的引用)。
答案 1 :(得分:3)
我认为这只能在展示位置new
的背景下有意义。如果引用所指向的对象是使用展示位置new
创建的,则应该可以销毁该对象并在位置new
的同一位置创建一个新对象。我现在没有看到任何立即使用指针的原因。
答案 2 :(得分:2)
这里是C ++标准的完整段落,我正在解读:
如果在对象的生命周期结束之后并且在重用或释放对象占用的存储之前,则在原始对象占用的存储位置创建新对象,指向原始对象的指针, 引用原始对象的引用,或原始对象的名称将自动引用新对象,并且一旦新对象的生命周期开始,就可以 用于操纵新对象 if:
- 新对象的存储空间正好覆盖原始对象占用的存储位置,
- 新对象与原始对象的类型相同(忽略顶级cv限定符),
- 原始对象的类型不是const限定的,如果是类类型,则不包含任何类型为const-qualified或引用类型的非静态数据成员,并且
- 原始对象是类型
T
的派生程度最高的对象(1.8),新对象是类型T
的派生程度最高的对象(也就是说,它们不是基类子对象)。 / LI>
"在存储位置创建一个新对象"正如midor观察到的那样,肯定是贴牌新的效果。
答案 3 :(得分:-1)
在封面下,引用只不过是自动解除引用指针,因此它们会遇到一些与指针相同的问题。引用可以是陈旧的,就像指针一样。引用引用的内存可以被其他对象重用,就像指针引用的内存一样。我认为所有这些陈述都试图说。
一个理智的程序员会故意利用这个吗?不太可能,我也不认为评论暗示你试图这样做(虽然技术上可行,使用贴牌新)。我认为更多的是阻止人们按照托管语言的思路进行思考,在这种语言中,仅仅存在引用就足以使对象保持活跃。