std::shared_ptr<T>::reset
来自cppreference.com
<tbody>
</tbody>
void reset() noexcept; |
(1) | (C++11 起) |
template< class Y > void reset( Y* ptr ); |
(2) | (C++11 起) |
template< class Y, class Deleter > void reset( Y* ptr, Deleter d ); |
(3) | (C++11 起) |
template< class Y, class Deleter, class Alloc > void reset( Y* ptr, Deleter d, Alloc alloc ); |
(4) | (C++11 起) |
以 ptr 所指向的对象替换被管理对象。能提供可选的删除器 d,之后在无 shared_ptr 对象占有该对象时以之销毁新对象。默认以 delete 表达式为删除器。始终选择对应提供类型的恰当 delete 表达式,这是函数以使用分离的形参 Y 的模板实现的理由。
若 *this 已拥有某个对象,且它是最后一个拥有该对象的 shared_ptr,则通过所拥有的删除器销毁此对象。
若 ptr 所指向的对象已被占有,则函数通常会导致未定义行为。
1) 释放被管理对象的所有权,若存在。调用后,
*this 不管理对象。等价于 shared_ptr().swap(*this);。2-4) 以
ptr 所指向对象替换被管理对象。Y 必须是完整类型且可隐式转换为 T。另外:2) 以 delete 表达式为删除器。合法的 delete 表达式必须可用,即
delete ptr 必须良构,拥有良好定义行为且不抛任何异常。等价于 shared_ptr<T>(ptr).swap(*this);。3) 以指定的删除器
d 为删除器。Deleter 必须对 T 类型可调用,即 d(ptr) 必须良构,拥有良好定义行为且不抛任何异常。Deleter 必须可复制构造 (CopyConstructible) ,且其复制构造函数和析构函数必须不抛异常。等价于 shared_ptr<T>(ptr, d).swap(*this);。4) 同 (3),但额外地用
alloc 的副本分配内部使用的数据。Alloc 必须是分配器 (Allocator) 。复制构造函数和析构函数必须不抛异常。等价于 shared_ptr<T>(ptr, d, alloc).swap(*this);。参数
| ptr | - | 指向要取得所有权的对象的指针 |
| d | - | 为删除对象而存储的删除器 |
| alloc | - | 进行内部分配所用的分配器 |
返回值
(无)
异常
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 (公开成员函数) |