- C++智能指针之shared_ptr
- shared_ptr篇
- 简介
- 成员函数
- 构造函数
- 默认构造
- 空指针构造
- 指针构造
- 指针构造 + 删除器
- 指针构造 + 删除器 + 内存分配器
- 拷贝构造
- 移动构造
- 从其它类型的管理指针移动构造
- 别名构造函数
- 析构函数
- get
- operator*
- operator->
- use_count
- unique
- operator bool
- owner_before
- operator
- swap
- reset
shared_ptr是一种定义在
如果俩个对象都是通过指针构造来的,那么他们是俩个对象指针,不会共享对象。
成员函数 构造函数 默认构造constexpr shared_ptr() noexcept;
{
std::cout << "nn";
std::shared_ptr p1;
std::cout << "p1 use count:" << p1.use_count() << 'n';
}
空指针构造
constexpr shared_ptr(nullptr_t) : shared_ptr() {}
{
std::cout << "nn";
std::shared_ptr p2(nullptr);
std::cout << "p2 use count:" << p2.use_count() << 'n';
}
指针构造
获取对象的所有权,并将use_count置为1。
templateexplicit shared_ptr (U* p);
{
std::cout << "nn";
std::shared_ptr p3(new TestPtr("p3"));
std::cout << "p3 use count:" << p3.use_count() << 'n';
}
指针构造 + 删除器
templateshared_ptr (U* p, D del); template shared_ptr (nullptr_t p, D del);
{
std::cout << "nn";
std::shared_ptr p4(new TestPtr("p4"), std::default_delete());
std::cout << "p4 use count:" << p4.use_count() << 'n';
}
指针构造 + 删除器 + 内存分配器
templateshared_ptr (U* p, D del, Alloc alloc); template shared_ptr (nullptr_t p, D del, Alloc alloc);
{
std::cout << "nn";
std::shared_ptr p5(new TestPtr("p5"), std::default_delete(), std::allocator());
std::cout << "p5 use count:" << p5.use_count() << 'n';
}
拷贝构造
若p不会空,则use_count加1;若p为空,则构造一个空对象。
shared_ptr (const shared_ptr& x) noexcept; templateshared_ptr (const shared_ptr& x) noexcept;
{
std::cout << "nn";
std::shared_ptr p(new TestPtr("p"));
std::shared_ptr p6(p);
std::cout << "p6 use count:" << p6.use_count() << 'n';
}
移动构造
获取P对象的所有权,并且P成为空对象。
shared_ptr (shared_ptr&& x) noexcept; templateshared_ptr (shared_ptr&& x) noexcept;
{
std::cout << "nn";
std::shared_ptr p(new TestPtr("p"));
std::cout << "p use count:" << p.use_count() << " -> " << p.get() << "n";
std::shared_ptr p7(std::move(p));
std::cout << "p7 use count:" << p7.use_count() << " -> " << p7.get() << "n";
std::cout << "p use count:" << p.use_count() << " -> " << p.get() << "n";
}
从其它类型的管理指针移动构造
获取p对象的所有权,并将use_count置为1,对象P释放所有权。
templateshared_ptr (auto_ptr&& x); template shared_ptr (unique_ptr&& x);
{
std::cout << "nn";
std::unique_ptr p(new TestPtr("unique_ptr"));
std::cout << " p-> " << p.get() << "n";
std::shared_ptr p8(std::move(p));
std::cout << "p8 use count:" << p8.use_count() << " -> " << p8.get() << "n";
std::cout << " p-> " << p.get() << "n";
}
别名构造函数
该对象不拥有 p,并且不会管理其存储。 相反,它共同拥有 x 的托管对象并算作 x 的一种附加用途。 它还将在释放时删除 x 的指针(而不是 p)它可以用来指向已经被管理的对象的成员。
templateshared_ptr (const shared_ptr& x, element_type* p) noexcept;
{
std::cout << "nn";
struct Data
{
int *total;
};
std::shared_ptr p = std::make_shared();
p->total = new int;
*p->total = 10;
std::cout << "p use count:" << p.use_count() << " -> " << p.get() << "n";
std::cout << "p->total:" << p->total << " -> " << *p->total << "n";
std::shared_ptr p9(p, p->total);
std::cout << "p9 use count:" << p9.use_count() << " -> " << p9.get() << "n";
std::cout << "p use count:" << p.use_count() << " -> " << p.get() << "n";
std::cout << "p->total:" << p->total << " -> " << *p->total << "n";
delete p->total;
}
析构函数
销毁shared_ptr对象:
- 如果 use_count 大于 1(即对象与其他 shared_ptr 对象共享其托管对象的所有权):与其共享所有权的其他对象的使用计数减 1。
- 如果 use_count 为 1(即对象是托管指针的唯一所有者):删除其拥有的指针指向的对象(如果 shared_ptr 对象是用特定的删除器构造的,则调用 this;否则,函数使用运算符 删除)。
- 如果 use_count 为零(即对象为空),则此析构函数没有副作用。
{
{
std::shared_ptr p0;
{
{
std::cout << "nn";
auto deleter = [](int *p)
{
delete p;
std::cout << "[deleter called] donen";
};
std::shared_ptr p(new int, deleter);
p0 = p;
std::cout << "p use count:" << p.use_count() << " -> " << p.get() << "n";
std::cout << "p0 use count:" << p0.use_count() << " -> " << p0.get() << "n";
}
// 在此 use_count 减为1,不析构
std::cout << "[OK] after leave pn";
std::cout << "p0 use count:" << p0.use_count() << " -> " << p0.get() << "n";
}
}
//在此 use_count 减为0,析构p
}
get
返回对象所存储指针的地址。
element_type* get() const noexcept;operator*
返回对象存储指针的解引用。
element_type& operator*() const noexcept;operator->
解引用对象管理指针的成员。
element_type* operator->() const noexcept;use_count
返回在与此对象(包括它)相同的指针上共享所有权的 shared_ptr 对象的数量。
long int use_count() const noexcept;unique
返回 shared_ptr 对象是否不与其他 shared_ptr 对象共享其指针的所有权(即,它是唯一的)。
bool unique() const noexcept;
{
std::shared_ptr p1(nullptr);
std::shared_ptr p2 = std::make_shared("p2");
std::shared_ptr p3 = std::make_shared("p3");
p1 = p2;
std::cout << "p1 unqiue :" << (p1.unique() ? " true" : " false") << "n"; // false
std::cout << "p2 unqiue :" << (p2.unique() ? " true" : " false") << "n"; // false
std::cout << "p3 unqiue :" << (p3.unique() ? " true" : " false") << "n"; // true
}
operator bool
检查对象存储的指针是否为空;
explicit operator bool() const noexcept;
{
std::shared_ptr p1(nullptr);
std::shared_ptr p2 = std::make_shared("p2");
std::cout << "p1 bool :" << (!p1 ? " true" : " false") << "n"; // false
std::cout << "p2 bool :" << (!p2 ? " true" : " false") << "n"; // true
}
owner_before
根据严格的所有者的弱顺序,返回对象是否被认为在 x 之前。
templatebool owner_before (const shared_ptr& x) const; template bool owner_before (const weak_ptr& x) const;
{
int* p = new int(10);
std::shared_ptr a(new int(20));
std::shared_ptr b(a, p); // 别名构造
std::shared_ptr c = a;
std::cout << "*a:" << *a << 'n';
std::cout << "*b:" << *b << 'n';
std::cout << "comparing a and b...n" << std::boolalpha;
std::cout << "value-based: " << (!(a < b) && !(b < a)) << 'n';
std::cout << "owner-based: " << (!a.owner_before(b) && !b.owner_before(a)) << 'n';
std::cout << "c is before a: " << (c.owner_before(a)) << 'n';
std::cout << "a is before : " << (a.owner_before(c)) << 'n';
std::cout << "b is before a: " << (b.owner_before(a)) << 'n';
delete p;
}
operator
- 复制(1) 将该对象添加为 x 资产的共享所有者,从而增加它们的 use_count。
shared_ptr& operator= (const shared_ptr& x) noexcept; templateshared_ptr& operator= (const shared_ptr& x) noexcept;
- 移动 (2) 将所有权从 x 转移到 shared_ptr 对象,而不改变 use_count。 x 变成一个空的 shared_ptr (就像默认构造的一样)。
shared_ptr& operator= (shared_ptr&& x) noexcept; templateshared_ptr& operator= (shared_ptr&& x) noexcept;
- 来自其他托管指针类型 (3) 的移动分配也转移所有权,并使用设置为使用计数 1 进行初始化。
templateshared_ptr& operator= (auto_ptr&& x); template shared_ptr& operator= (unique_ptr&& x);
- 此外,在上述所有情况下,调用此函数的副作用与在其值更改之前调用 shared_ptr 的析构函数具有相同的副作用(如果此 shared_ptr 是唯一的,则包括删除托管对象)。
- 不能将指针的值直接分配给 shared_ptr 对象。 可以使用 make_shared 或 member reset 代替。
{
std::shared_ptr p1(nullptr);
std::shared_ptr p2 = make_shared("p2");
std::shared_ptr p3 = make_shared("p3");
std::cout << "A:n";
std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n';
std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n';
std::cout << "p3 use count:" << p3.use_count() << ' ' << p3.get() << 'n';
p1 = p2;
std::cout << "copy:n";
std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n';
std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n';
std::cout << "p3 use count:" << p3.use_count() << ' ' << p3.get() << 'n';
p1 = std::move(p3);
std::cout << "move:n";
std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n';
std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n';
std::cout << "p3 use count:" << p3.use_count() << ' ' << p3.get() << 'n';
}
swap
交换对象所有权,将 shared_ptr 对象的内容与 x 的内容交换,在它们之间转移任何托管对象的所有权,而不会破坏或更改其中任何一个的使用计数。
void swap (shared_ptr& x) noexcept;
{
std::shared_ptr p1 = make_shared("p1");
std::shared_ptr p2 = make_shared("p2");
std::shared_ptr p3(nullptr);
std::cout << "init:n";
std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n'; // 1
std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n'; // 1
std::cout << "p3 use count:" << p3.use_count() << ' ' << p3.get() << 'n'; // 0
p1.swap(p2);
std::cout << "swap p2 -> p1:n";
std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n'; // 1
std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n'; // 1
std::cout << "p3 use count:" << p3.use_count() << ' ' << p3.get() << 'n'; // 0
p3.swap(p1);
std::cout << "swap p1 -> p3:n";
std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n'; // 0
std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n'; // 1
std::cout << "p3 use count:" << p3.use_count() << ' ' << p3.get() << 'n'; // 1
}
reset
(1) void reset() noexcept; (2) templatevoid reset (U* p); (3) template void reset (U* p, D del); (4) template void reset (U* p, D del, Alloc alloc);
- 对于 reset (1),对象变为空(就像默认构造的一样),释放所有权。
- 在其他情况下,shared_ptr 获得 p 的所有权,使用计数为 1,并且 - 可选 - 分别使用 del 和/或 alloc 作为删除器和分配器。
- 调用此函数具有与 shared_ptr 的析构函数在其值更改之前调用相同的副作用(包括如果此 shared_ptr 是唯一的则删除托管对象)。
{
std::shared_ptr p1(nullptr);
std::shared_ptr p2 = make_shared("p2");
std::cout << "init:n";
std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n'; // 0
std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n'; // 1
p1.reset(new TestPtr("new p1"));
p2.reset();
std::cout << "reset:n";
std::cout << "p1 use count:" << p1.use_count() << ' ' << p1.get() << 'n'; // 1
std::cout << "p2 use count:" << p2.use_count() << ' ' << p2.get() << 'n'; // 0
}



