C++ 入门 5 版 : using get member to initialize another shared_ptr independent object

标签 c++ shared-ptr

关于 C++ primer 5 版。第 12 章动态内存。

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
  // undefined: two independent shared_ptrs point to the same memory
    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

In this case, both p and q point to the same memory. Because they were created independently from each other, each has a reference count of 1. When the block in which q was defined ends, q is destroyed. Destroying q frees the memory to which q points. That makes p into a dangling pointer, meaning that what happens when we attempt to use p is undefined. Moreover, when p is destroyed, the pointer to that memory will be deleted a second time.

如我所见,q 不是 shared_ptr 而是内置指针,因此它没有引用计数。通常他应该说临时 shared_ptr 对象和 p 代替。不是吗?

  • 此外,我认为这段代码不会导致未定义的行为!因为我已经尝试过并且运行良好。因为我猜是这样的表达:

    { // new block
      // undefined: two independent shared_ptrs point to the same memory
        shared_ptr<int>(q); // I think this will be removed by the compiler as an optimization.
    }
    

因此我认为只有一个 shared_ptr 管理该内存。所以我认为这是安全的。但如果他写道:

{ // new block
  // undefined: two independent shared_ptrs point to the same memory
    shared_ptr<int> q2(q);
} 

那么这就是他的意思。 谢谢!

最佳答案

呈现的代码确实有问题并且没有显示它想要显示的内容,但不是因为某些假定的编译器优化...

行:

shared_ptr<int>(q);

不会创建一个新的临时 shared_ptr,其中 q 是发送到 shared_ptr 的构造函数的参数! 它创建一个名为 q 的 shared_ptr。

所以这确实是一个错误的代码示例,您提出的修复是正确的。

然而,正如评论中提到的,以下哲学:它运行因此它不是未定义的行为是错误的。

示例中代码的另一个修复可能是使用花括号 {} 将 q 作为临时 shared_ptr 的参数发送:

int main() {
    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
      // undefined: two independent shared_ptrs point to the same memory
        shared_ptr<int> {q}; // q is now a parameter to a temporary shared_ptr
    } // 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
}

最后一点 - 为 block 内的 shared_ptr 命名的建议并没有真正放弃编译器优化,只要不使用实际对象,编译器可能会放弃它的创建。因此,如果您想确保编译器优化不会发生,您应该这样做:

int main() {
    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
      // undefined: two independent shared_ptrs point to the same memory
        shared_ptr<int> ptr {q}; // q is now a parameter to a local shared_ptr
        *ptr = 42; // do something with ptr
    } // 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
    return foo; // do something with foo
}

关于C++ 入门 5 版 : using get member to initialize another shared_ptr independent object,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58583891/

相关文章:

c++ - 从函数返回后更改对象值

c++ - Boost 1.59.0 如何清理项目?

c++ - boost::smart_ptr 的内部结构

c++ - Shared_ptr 没有可行的重载 '='

c++ - 在多作者情况下如何对文件支持的共享内存中的大页进行故障处理

c++ - 在 C++ 中复制具有特定更改的 vector 的最快方法

c++ - rogue like 游戏初始化错误

c++ - 不存在合适的构造函数来从 "dumb pointer"转换为 "smart pointer"

C++17:unique_ptr<char[]> 和shared_ptr<char[]> 之间指针存储的差异

c++ - 检测对象是否为智能指针所有