std::shared_ptr<T>::reset

来自cppreference.com
 
 
内存管理库
(仅用于阐述*)
分配器
未初始化内存算法
受约束的未初始化内存算法
内存资源
未初始化存储 (C++20 前)
(C++17 弃用)
(C++17 弃用)

垃圾收集器支持 (C++23 前)
(C++11)(C++23 前)
(C++11)(C++23 前)
(C++11)(C++23 前)
(C++11)(C++23 前)
(C++11)(C++23 前)
(C++11)(C++23 前)
 
 
void reset() noexcept;
(1) (C++11 起)
(C++26 起为 constexpr)
template< class Y > 
void reset( Y* ptr );
(2) (C++11 起)
(C++26 起为 constexpr)
template< class Y, class Deleter > 
void reset( Y* ptr, Deleter d );
(3) (C++11 起)
(C++26 起为 constexpr)
template< class Y, class Deleter, class Alloc > 
void reset( Y* ptr, Deleter d, Alloc alloc );
(4) (C++11 起)
(C++26 起为 constexpr)

ptr 所指向的对象替换被管理对象。能提供可选的删除器 d,之后在无 shared_ptr 对象占有该对象时以之销毁新对象。

如果 *this 已拥有某个对象,且它是最后一个拥有该对象的 shared_ptr,那么通过所拥有的删除器销毁此对象。

1) 释放被管理对象的所有权(如果存在)。调用后,*this 不管理对象。
等价于 shared_ptr<T>().swap(*this);
2-4)ptr 所指向对象替换被管理对象。
2)delete 表达式为删除器。
等价于 shared_ptr<T>(ptr).swap(*this);
3) 以指定的删除器 d 为删除器。
等价于 shared_ptr<T>(ptr, d).swap(*this);
4)(3),但额外地用 alloc 的副本分配内部使用的数据。
等价于 shared_ptr<T>(ptr, d, alloc).swap(*this);

参数

ptr - 指向要取得所有权的对象的指针
d - 为删除对象而存储的删除器
alloc - 进行内部分配所用的分配器

注解

始终选择对应提供类型的恰当 delete 表达式,这是函数以使用分离的形参 Y 的模板实现的理由。

为使内部调用的 shared_ptr 构造函数具有定义良好的行为,也需要满足与其相同的条件。例如在 ptr 指向的对象已经由另外某个 shared_ptr 拥有的情况下,调用此函数很可能导致未定义行为。

异常

2) 无法获得要求的额外内存时会抛出 std::bad_alloc。可能因其他错误抛出由实现定义的异常。出现异常时会求值 delete ptr
3,4) 无法获得要求的额外内存时会抛出 std::bad_alloc。可能因其他错误抛出由实现定义的异常。出现异常时会求值 d(ptr)

示例

#include <iostream>
#include <memory>

struct Foo
{
    Foo(int n = 0) noexcept : bar(n)
    {
        std::cout << "Foo::Foo(),bar = " << bar << " @ " << this << '\n';
    }
    ~Foo()
    {
        std::cout << "Foo::~Foo(),bar = " << bar << " @ " << this << '\n';
    }
    int getBar() const noexcept { return bar; }
private:
    int bar;
};

int main()
{
    std::cout << "1) 独占所有权\n";
    {
        std::shared_ptr<Foo> sptr = std::make_shared<Foo>(100);
        
        std::cout << "Foo::bar = " << sptr->getBar() << ",use_count() = "
                  << sptr.use_count() << '\n';
        
        // 重置 shared_ptr 而不给它新的 Foo 实例。
        // 此调用后原实例将被销毁。
        std::cout << "调用 sptr.reset()...\n";
        sptr.reset(); // 此处调用 Foo 的析构函数
        std::cout << "调用 reset() 后:use_count() = " << sptr.use_count()
                  << ",sptr = " << sptr << '\n';
    }   // 不调用 Foo 的析构函数,已在早前的 reset() 中调用
    
    std::cout << "\n2) 独占所有权\n";
    {
        std::shared_ptr<Foo> sptr = std::make_shared<Foo>(200);
        
        std::cout << "Foo::bar = " << sptr->getBar() << ",use_count() = "
                  << sptr.use_count() << '\n';
        
        // 重置 shared_ptr,传给它 Foo 的新实例。
        // 此调用后原实例将被销毁。
        std::cout << "调用 sptr.reset()...\n";
        sptr.reset(new Foo{222});
        std::cout << "调用 reset() 后:use_count() = " << sptr.use_count()
                  << ",sptr = " << sptr << "\n离开作用域...\n";
    }   // 调用 Foo 的析构函数。
    
    std::cout << "\n3) 多重所有权\n";
    {
        std::shared_ptr<Foo> sptr1 = std::make_shared<Foo>(300);
        std::shared_ptr<Foo> sptr2 = sptr1;
        std::shared_ptr<Foo> sptr3 = sptr2;
        
        std::cout << "Foo::bar = " << sptr1->getBar() << ",use_count() = "
                  << sptr1.use_count() << '\n';
        
        // 重置 shared_ptr sptr1,传给它 Foo 的新实例。
        // 原实例仍在 sptr2 和 sptr3 之间共享。
        std::cout << "调用 sptr1.reset()...\n";
        sptr1.reset(new Foo{333});

        std::cout << "调用 reset() 后:\n"
                  << "sptr1.use_count() = " << sptr1.use_count()
                  << ",sptr1 @ " << sptr1 << '\n'
                  << "sptr2.use_count() = " << sptr2.use_count()
                  << ",sptr2 @ " << sptr2 << '\n'
                  << "sptr3.use_count() = " << sptr3.use_count()
                  << ",sptr3 @ " << sptr3 << '\n'
                  << "离开作用域...\n";
    }   // 调用两个析构函数:1) sptr1 所拥有的 Foo,
        // 2) sptr2/sptr3 所共享的 Foo。
}

可能的输出:

1) 独占所有权
Foo::Foo(),bar = 100 @ 0x23c5040
Foo::bar = 100,use_count() = 1
调用 sptr.reset()...
Foo::~Foo(),bar = 100 @ 0x23c5040
调用 reset() 后:use_count() = 0,sptr = 0

2) 独占所有权
Foo::Foo(),bar = 200 @ 0x23c5040
Foo::bar = 200,use_count() = 1
调用 sptr.reset()...
Foo::Foo(),bar = 222 @ 0x23c5050
Foo::~Foo(),bar = 200 @ 0x23c5040
调用 reset() 后:use_count() = 1,sptr = 0x23c5050
离开作用域...
Foo::~Foo(),bar = 222 @ 0x23c5050

3) 多重所有权
Foo::Foo(),bar = 300 @ 0x23c5080
Foo::bar = 300,use_count() = 3
调用 sptr1.reset()...
Foo::Foo(),bar = 333 @ 0x23c5050
调用 reset() 后:
sptr1.use_count() = 1,sptr1 @ 0x23c5050
sptr2.use_count() = 2,sptr2 @ 0x23c5080
sptr3.use_count() = 2,sptr3 @ 0x23c5080
离开作用域...
Foo::~Foo(),bar = 300 @ 0x23c5080
Foo::~Foo(),bar = 333 @ 0x23c5050

参阅

构造新的 shared_ptr
(公开成员函数) [编辑]