对新对象使用相同的引用

Using the same Reference for a new object

本文关键字:引用 新对象 对象      更新时间:2023-10-16

在搜索一些松散相关的东西时,我遇到了这样一句话:

引用可以比对象更长寿,并且可以用来引用在同一地址创建的新对象。

根据这个答案。

现在,我一直知道引用是不可变的,初始化过一次。读到上面一句话,可能是一个比我更有经验的人说的,让我怀疑自己是否错过了什么。

这句话是为了完整而实际上不适用吗?

是否存在这样的模式或情况:人们会经历将同一类型的新对象放在特定的内存地址中的痛苦,只是为了切换以获得参考?(对我来说,这似乎极其危险,更不用说在最好的时候令人费解了(。

我认为这只有在放置new的上下文中才有意义。如果参考点所指向的对象是用放置new创建的,则应该可以销毁该对象,并在放置new的同一位置再次创建新对象。不过,我认为目前没有任何直接的理由不使用指针。

悬挂引用的问题本质上与悬挂指针的问题相同。

例如,的两个功能

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(来创建悬空引用或指针也会发生同样的情况。

如果其他代码(最终(使用该内存(例如,表示另一个变量,表示一个不相关的对象(,则该引用或指针通常可以访问该内存位置的任何内容。这可能会带来值更改的虚假问题(这可能会给使用引用的代码或发现变量或对象被更改的无关代码带来惊喜(。

它不是一件值得向往或实际使用的东西。这是一个危险的程序缺陷,通常很难修复或调试,因为它为两个完全不相关的代码段提供了一条路径,以影响另一个使用的数据。

幸运的是,现代编译器通常(如果配置为提供最大警告级别(确实会对许多可疑结构(例如,返回指针或对局部变量的引用(发出警告。

如果在对象的生命周期结束后,在对象所占用的存储被重用或释放之前,在原始对象所占据的存储位置创建了一个新对象,指向原始对象的指针,引用原始对象的引用,或者原始对象的名称将自动引用新对象,并且一旦新对象的生存期开始,就可以用于操作新对象,如果:

  • 新对象的存储正好覆盖原始对象所占用的存储位置,以及
  • 新对象与原始对象的类型相同(忽略顶级cv限定符(,并且
  • 原始对象的类型不是const限定的,如果是类类型,则不包含任何类型是const限定或引用类型的非静态数据成员,并且
  • 原始对象是类型为T的最派生对象(1.8(并且新对象是类型T的最派生的对象(即它们不是基类子对象(

正如midor所观察到的,"在存储位置创建了一个新对象"无疑是放置新对象的效果。

在本质上,引用只不过是自动取消引用指针,因此它们与指针存在一些相同的问题。引用可能是过时的,就像指针一样。引用引用的内存可以被其他对象重用,就像指针引用的内存一样。我想这就是所讨论的全部内容。

一个理智的程序员会有意利用这一点吗?不太可能,我也不认为这条评论是在暗示你尝试这样做(尽管从技术上讲,使用新的位置是可能的(。我认为这更多的是为了防止人们按照托管语言的思路思考,在托管语言中,仅仅存在引用就足以让对象保持活力。