当按引用传递参数存储在被调用方对象中,然后被调用方删除时会发生什么情况

What happens when a pass-by-reference parameter gets stored in the callee object, and then deleted by the caller?

本文关键字:调用 删除 什么情况 方删除 然后 对象 存储 参数 按引用传递 方对象      更新时间:2023-10-16
来自

C,我对C++的'引用'对象概念很陌生。为了帮助自己弄清楚,我对观察者模式的实现进行了轻微修改。

A类:

class A
{
   public:
      A (int x) : m_x (x) {}
   private:
      int m_x;
}

B类:

class B
{
   public:
      void Register (A& listener) { m_currentListener = listener; }
   private:
      A& m_currentListener;
}

C类:

class C
{
   public:
      void RegisterNewDefaultListener ()
      {
         A tempA (42);
         m_observer.Register (tempA);
         m_lastRegisteredListener= tempA;
      }
   private:
      B m_observer;
      A& m_lastRegisteredListener;
}

这是我担心C#RegisterNewDefaultListener的方法:它创建一个本地实例A,然后通过引用将其传递到两个不同的地方并将其存储起来。

但是,该本地实例会立即超出范围,并将被破坏。那些保留该引用的别名会发生什么情况?它们会失效吗?还是说,在对它的所有引用也消失之前,本地A不会消失?

很难说你在问什么。 对于初学者来说,课程B需要一个构造函数才能编译,正是因为它包含引用:该引用必须在构造函数中初始化,并且以后永远无法更改。 同样的事情也适用于C.

当然,您可以通过使用指针来实现相同的效果,然后您可以在构造函数运行后更改它们。 和注册局部变量的地址,其寿命将超过该变量局部变量通常是一个坏主意;如果是听众,你是有兴趣的,听众自己一般会做注册,跟踪其注册位置,并将在其破坏者。 (它通常也会在收到相关事件。 但是你没有说你的实际问题是什么。

更一般地说,悬空引用和指针是一个问题关于所有语言;由于某种原因,听众变成了不相关或不活动,并且必须自行注销。 C++不是在这方面与任何其他语言都不同。

在这种特殊情况下,引用的行为方式与 C 指针非常相似 - 它们将引用不存在的实例,坏事将随之而来。通常,引用不会被存储(有一些值得注意的例外) - 它们主要用于传递参数而不复制它们,调用方提供其有效性的保证,直到被调用的方法完成。

它的工作方式与指针相同,如果对象不再存在,则尝试访问该对象会导致未定义的行为。

如果你在class B中有A& m_currentListener;,这意味着你必须将其初始化为构造函数中的某些东西(即将引用绑定到对象),否则代码将无法编译。所以让我们假设你有(相当丑陋,但在这里并不重要):

B::B() : m_currentListener(*new A(0)) {}

然后B::Register() m_currentListener引用的对象分配给传递给该函数的listener的副本。您不会重新绑定m_currentListener以引用其他对象!因此,这里没有未定义的行为,但代码可能不是您想要的方式工作。