当pass-by-reference参数存储在被调用者对象中,然后被调用者删除时会发生什么?

时间:2014-11-26 18:56:30

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

来自C,我是C ++的'参考'对象概念的新手。为了帮助自己解决这个问题,我对Observer模式进行了略微修改。

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是否会消失,直到所有引用它都消失了?

4 个答案:

答案 0 :(得分:4)

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

当然,您可以通过使用指针来实现相同的效果,然后 你可以在构造函数运行后更改它们。并注册 一个局部变量的地址,其中的某些东西会比这个变量更长久 局部变量通常是个坏主意;如果是听众你就是 感兴趣的是,听众本身一般会做注册, 跟踪它注册的位置,并在其中注销自己 析构函数。 (它通常也会在收到时自行删除 相关事件。)但你没有说出你的实际问题是什么。

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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

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

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