来自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
是否会消失,直到所有引用它都消失了?
答案 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
来引用不同的对象!所以这里没有未定义的行为,但代码可能不是你想要的。