std :: shared_ptr:reset()与赋值

Alw*_*ing 40 c++ shared-ptr c++11

这是一个基本问题,但我没有找到关于它的先前帖子.以下问题的标题听起来可能与我的问题相同,但问题本身与标题不匹配:使用shared_ptr.reset还是operator =?

我对reset()成员函数的目的感到困惑std::shared_ptr:除了赋值运算符之外,它还有什么作用呢?

具体来说,给定定义:

auto p = std::make_shared<int>(1);
Run Code Online (Sandbox Code Playgroud)
  1. 以下两行是否相同:

    p = std::make_shared<int>(5);
    p.reset(new int(5));
    
    Run Code Online (Sandbox Code Playgroud)
  2. 这些怎么样:

    p = nullptr;
    p.reset();
    
    Run Code Online (Sandbox Code Playgroud)

如果两条线在两种情况下都相同,那么目的是reset()什么?


编辑:让我重新说一下这个问题,以便更好地强调它的观点.问题是:是否有一种情况reset()可以让我们在没有它的情况下实现一些不容易实现的事情?

Nat*_*ica 24

当使用reset()传递给reset的参数时,不需要是一个托管对象(也不是); 而=右手边必须是管理对象.

所以这两行给出了相同的最终结果:

p = std::make_shared<int>(5); // assign to a newly created shared pointer
p.reset(new int(5)); // take control of a newly created pointer
Run Code Online (Sandbox Code Playgroud)

但我们做不到:

p = new int(5); // compiler error no suitable overload
p.reset(std::make_shared<int>(5).get()); // uh oh undefined behavior
Run Code Online (Sandbox Code Playgroud)

如果没有reset()您将无法在不创建共享指针和分配指针的情况下将共享指针重新分配给不同的原始指针.没有=你将无法使共享指针指向另一个共享指针.

  • 我理解不同的用法.我的问题是:是否有一种情况,`reset()`让我实现了没有它就不容易实现的东西? (2认同)
  • 由`make_shared`创建的共享ptr与由`.reset(new T)`创建的共享ptr不同. (2认同)
  • @MaxNoe 使用“make_shared”指针,可以使用对 new 的单次调用将共享状态分配到单个对象中。当您重置时,必须将其分为两个单独的分配。 (2认同)

Pra*_*ian 6

这是可能的reset,以避免在某些情况下,动态内存分配.考虑一下代码

std::shared_ptr<int> p{new int{}};  // 1
p.reset(new int{});                 // 2
Run Code Online (Sandbox Code Playgroud)

在第1行,发生了2个动态内存分配,一个用于int对象,第二个用于shared_ptr控制块,它将跟踪对被管理对象的强/弱引用的数量.

在第2行,还有一个新int对象的动态内存分配.在身体resetshared_ptr将确定有先前管理没有其它强引用int,所以它必须delete它.由于也没有任何弱引用,它也可以解除分配控制块,但在这种情况下,重复使用相同的控制块将是谨慎的,因为否则它将不得不分配新的控制块.

如果您总是必须使用赋值,则无法执行上述操作.

std::shared_ptr<int> p{new int{}};    // 1
p = std::shared_ptr<int>{new int{}};  // 2
Run Code Online (Sandbox Code Playgroud)

在这种情况下,第2 shared_ptr行对构造函数的第二次调用已经分配了一个控制块,因此p必须释放它自己的现有控制块.

  • @ChrisDrew是的,测量很重要,因为在更大的范围内,重置速度更快并不明显,因为 make_shared 在单个分配中创建了控制块和对象,这意味着在使用缓存局部性时可能会导致“make_shared”根据生成的“shared_ptr”的实际使用方式来赢得“reset”。换句话说,仅查看修改shared_ptr的性能是不够的,还要查看修改+使用的综合性能影响。(这排除了没有任何实际使用场景的小型通用测试)。 (2认同)