我对 “一个对象已返回内存堆” 部分有疑问。 返回是否意味着对象已被释放?如果没有,为什么拥有指向该对象的指针/引用是一场灾难?
分解术语并澄清一些事情可能会有所帮助:
首先,C++中的Object一词是指something驻留在内存中,而不是指内存本身。
区分对象和存储对象的内存是值得的,因为分配内存和初始化对象的操作是不同的和独立的。
下面这行做了两件事:
new int(123);
鉴于new 运算符正在执行两种不同的操作,因此delete 运算符也可以执行两种不同的操作:
delete 将销毁对象;这通常仅限于释放对象拥有的资源。销毁对象通常不会费心更改或重置任何即将被释放的内存,因为这通常会浪费 CPU 周期。
对象被销毁后,您可能会发现该对象的残骸或部分残骸在内存中停留了一段时间,但就您的程序而言,对象本身已死/消失,内存内容是垃圾。
delete 将取消分配内存。解除分配的过程并不是要改变那块内存的内容,它只是释放那块内存供其他东西使用。在内存被释放后尝试访问该内存区域是未定义的行为。
请记住,指针永远不能指向对象,因为对象是“内存中的事物”,而不是内存本身; C++ 中的原始指针相当简单/愚蠢——它们不跟踪任何关于对象在其指向的内存中的状态。如果一个对象被移动、复制或销毁,指针将一无所知。
指针是内存中某个位置的地址。
想一想 pointer-values(地址)和包含这些值/地址的 pointer-variables 会有所帮助。遗憾的是,pointer 一词在历史上具有双重含义,既指指针值又指指针地址,这似乎令人困惑。
通常,指针变量指向的内存位置应该在已分配的内存区域内包含有效对象,但也可能不包含。
C++ 不会保护您免受悬空指针的影响,其中 悬空指针 是一个指针变量,其中包含尚未分配给程序的内存区域的地址。
C++ 也不保护您免受指向未初始化内存的指针的影响(例如,如果您已使用 malloc 分配内存但未初始化其内容)。
最后,C++ 不能保护您免受内存泄漏;作为程序员,您有责任跟踪您分配的所有内存。
最后 3 点是 new/delete 在现代 C++ 中不经常使用的众多原因之一,以及为什么 & 引用、std::vector、std::shared_ptr 和其他替代方法优先;他们处理新/删除周围的许多细微差别和陷阱。