【发布时间】:2021-06-05 11:41:19
【问题描述】:
您好,我正在阅读 C++ 入门第 5 版,我想我在 shared_ptr 部分下发现了一个错误。首先,我正在编写代码和他们给出的解释。然后我会写出我认为是错误的内容以及我认为实际发生的事情。代码如下:
shared_ptr<int> p(new int(42));// reference count is 1
int *q = p.get();// ok: but don't use q in any way that might delete its pointer
{//new block started
shared_ptr<int>(q);
}// block ends, q is destroyed, and the memory to which q points is freed
int foo = *p;// undefined; the memory to which p points was freed
他们给出的解释如下:
在这种情况下,p 和 q 都指向同一个内存。因为它们是相互独立创建的,所以每个引用计数为 1。当定义 q 的块结束时,q 被销毁。销毁 q 会释放 q 指向的内存。这使得 p 成为一个悬空指针,这意味着当我们尝试使用 p 时发生的事情是未定义的。此外,当 p 被销毁时,指向该内存的指针将被第二次删除。
现在我认为错误是语句“当定义 q 的块结束时,q 被销毁。销毁 q 释放 q 指向的内存。”以及他们给出的推理为什么 p 是一个悬空指针的背后是错误的。以下是我为什么 p 是一个悬空指针以及为什么第一个引用的语句是错误的原因。
- 当定义 q 的块结束时,
q被销毁。但是q指向的内存没有被释放,因为q是内置指针而不是shared_ptr。除非我们显式地写 deleteq,否则相应的内存不会被释放。 - 现在,在新块中,我们使用 q 创建了一个临时 shared_ptr。但是这个临时的独立于
p。所以当这个内部块结束时,临时被破坏,因此内存被释放。但请注意,p仍然指向已释放的同一内存。所以p现在是一个悬空指针,在int foo=*p语句中使用p是未定义的。
我认为这是对为什么 p 是悬空指针的正确解释,也是应该存在的更正。有人可以确认这是对的还是我做错了什么?
【问题讨论】:
-
你说的是对的。该代码可以很好地演示
p最终悬空,但本书的措辞有点误导,因为它将q本身描述为shared_ptr而不是从q的内存中创建shared_ptr正在指向。 -
2 个不同的共享指针(不同的控制块)被创建,拥有相同的原始指针。当其中一个被摧毁时,另一个被悬空。
-
我认为这是书中的一个错字,内块应该是
std::shared_ptr<int> q(p.get());(而不是重用外块的名称)。 -
注:第 12.1.3 节(第 466 页)
标签: c++ c++11 c++14 shared-ptr errata