当按引用传递参数存储在被调用方对象中,然后被调用方删除时会发生什么情况
What happens when a pass-by-reference parameter gets stored in the callee object, and then deleted by the caller?
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
以引用其他对象!因此,这里没有未定义的行为,但代码可能不是您想要的方式工作。
- 是否有C++编译器选项允许激进地删除所有函数调用,并将参数传递给具有空体的函数
- 如何知道何时调用删除以及何时调用 delete[] C++?
- 真的有必要在这个指针上调用删除吗?
- 如何使用一个 VirtualFree 调用删除多个相邻的虚拟内存分配?
- 一个可以指向任何地方的指针,如何确定是否可以安全地调用"删除"
- 通过在C 中动态加载的LIB分配的基础级指针上调用删除的安全性
- 为什么当我尝试对使用 New 函数启动的对象调用删除函数时出现范围错误?
- 代码在调用删除时崩溃
- 在指针上调用删除时发生C 崩溃
- 您是否在C++的析构函数中调用删除
- C++,在基类上调用删除会导致
- 调用删除会导致程序冻结C++
- 调用删除时应用程序崩溃
- 调用删除 [] 时C++堆错误
- C++模板代码导致在显然未正确分配的对象上调用删除错误
- 调用删除时分段错误
- 迭代映射并调用删除其他元素的函数就是映射
- 用户界面 - C++:在事件驱动系统中间接调用“删除此内容”(例如在GUI应用程序中)
- 如何从 C++ 中的外部函数调用删除运算符
- 如果我在使用新的和结束的程序分配数据后没有调用删除运算符,会发生什么情况?