对新对象使用相同的引用

Using the same Reference for a new object

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

And a reference can outlive an object and be used to refer to a new object created at the same address.

由此answer.

现在,我一直都知道引用是不可变的,并且只初始化一次就可以了。 阅读上面的引用,可能比我更有经验,让我想知道我是否遗漏了什么。

那句话是不是为了完整而实际不适用?

是否存在某种模式或情况,人们会经历在特定内存地址中放置相同类型的新对象的痛苦,只是为了做一个 switcheroo 以供参考? (这对我来说似乎非常危险,更不用说在最好的时候令人费解了)。

悬挂引用的问题与悬挂指针的问题本质上是一样的。

比如两个函数

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

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

它不是值得渴望或实际使用的东西。这是一个危险的程序缺陷,通常很难修复或调试 - 因为它为两个完全不相关的代码部分提供了影响彼此使用的数据的途径。

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

我认为这只有在展示位置 new 的情况下才有意义。如果引用指向的对象是使用放置 new 创建的,则应该可以销毁该对象并在同一位置再次使用放置 new 创建一个新对象。不过,我目前没有看到不使用指针的任何直接理由。

在幕后,引用只不过是自动解引用指针,因此它们会遇到一些与指针相同的问题。引用可能会过时,就像指针一样。引用引用的内存可以被其他对象重用,就像指针引用的内存一样。我认为这就是所讨论的所有陈述。

一个理智的程序员会故意利用这个吗?不太可能,我也不认为评论是在建议您尝试这样做(尽管从技术上讲是可能的,使用 placement new)。我认为这更多是为了防止人们沿着托管语言的思路思考,在托管语言中,仅存在引用就足以使对象保持活动状态。

这是 C++ 标准的完整段落,我正在解释:

If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if:

  • the storage for the new object exactly overlays the storage location which the original object occupied, and
  • the new object is of the same type as the original object (ignoring the top-level cv-qualifiers), and
  • the type of the original object is not const-qualified, and, if a class type, does not contain any non-static data member whose type is const-qualified or a reference type, and
  • the original object was a most derived object (1.8) of type T and the new object is a most derived object of type T (that is, they are not base class subobjects).

"A new object is created at the storage location" 肯定是 placement-new 的效果,正如 midor 所观察到的。