【问题标题】:What happens when a pass-by-reference parameter gets stored in the callee object, and then deleted by the caller?当引用传递参数存储在被调用对象中,然后被调用者删除时会发生什么?
【发布时间】:2014-11-26 18:56:30
【问题描述】:

来自 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 在所有对它的引用都消失之前不会消失?

【问题讨论】:

  • 是的,当对象被销毁时,这些引用将无效,并且任何访问成员变量或对该对象引用调用非静态成员函数的尝试都将导致未定义的行为。
  • 顺便说一句:在 C++ 中,我们写成 C::RegisterNewDefaultListener(而不是 #)。

标签: c++ reference scope pass-by-reference observer-pattern


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

          猜你喜欢
          • 2022-06-27
          • 2013-07-04
          • 2012-11-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-03-18
          • 2016-04-29
          • 2012-06-04
          相关资源
          最近更新 更多