shared_ptr共享它指向的对象,多个shared_ptr可以指向(关联)相同的对象,在内部采用计数机制来实现。
当新的shared_ptr与对象关联时,引用计数增加1。
当shared_ptr超出作用域时,引用计数减1。当引用计数变为0时,则表示没有任何shared_ptr与对象关联,则释放该对象。
shared_ptr的构造函数也是explicit,但是,没有删除拷贝构造函数和赋值函数。
1)初始化
方法一:
shared_ptr
p0(new AA("zq ")); // 分配内存并初始化。
方法二:
shared_ptr
p0 = make_shared "); // C++11标准,效率更高。("zq shared_ptr
pp1=make_shared 数据类型为int。(); // shared_ptr
pp2 = make_shared 数据类型为AA,默认构造函数。(); // shared_ptr
pp3 = make_shared "); // 数据类型为AA,一个参数的构造函数。("zq shared_ptr
pp4 = make_shared ",8); // 数据类型为AA,两个参数的构造函数。("zq
方法三:
AA* p = new AA("zq");
shared_ptr
p0(p); // 用已存在的地址初始化。
方法四:
shared_ptr
p0(new AA("zq "));shared_ptr
p1(p0); // 用已存在的shared_ptr初始化,计数加1。shared_ptr
p1=p0; // 用已存在的shared_ptr初始化,计数加1。
2)使用方法
3)用于函数的参数
与unique_ptr的原理相同。
4)不支持指针的运算(+、-、++、--)
1)将一个unique_ptr赋给另一个时,如果源unique_ptr是一个临时右值,编译器允许这样做;如果源unique_ptr将存在一段时间,编译器禁止这样做。一般用于函数的返回值。
1 ) shared_ptr允许这样做。
2)用nullptr给shared_ptr赋值将把计数减1,如果计数为0,将释放对象,空的shared_ptr==nullptr。
3)release()释放对原始指针的控制权,将unique_ptr置为空,返回裸指针。
3) shared_ptr 不存在释放的操作,控制权不是由一个人说了算的。
4)std::move()可以转移对原始指针的控制权。还可以将unique_ptr转移成shared_ptr。
5)reset()改变与资源的关联关系。
pp.reset(); // 解除与资源的关系,资源的引用计数减1。
pp. reset(new AA("bbb")); // 解除与资源的关系,资源的引用计数减1。关联新资源。
6)swap()交换两个shared_ptr的控制权。
void swap(shared_ptr
7)shared_ptr也可象普通指针那样,当指向一个类继承体系的基类对象时,也具有多态性质,如同使用裸指针管理基类对象和派生类对象那样。
8)shared_ptr不是绝对安全,如果程序中调用exit()退出,全局的shared_ptr可以自动释放,但局部的shared_ptr无法释放。
9)shared_ptr提供了支持数组的具体化版本。
数组版本的shared_ptr,重载了操作符[],操作符[]返回的是引用,可以作为左值使用。
10)shared_ptr的线程安全性:
11)如果unique_ptr能解决问题,就不要用shared_ptr。unique_ptr的效率更高,占用的资源更少。
示例1:
#include
#include
using namespace std;
class AA
{
public:
string m_name;
AA() { cout << m_name << "调用构造函数AA()。\n"; }
AA(const string & name) : m_name(name) { cout << "调用构造函数AA("<< m_name << ")。\n"; }
~AA() { cout << "调用了析构函数~AA(" << m_name << ")。\n"; }
};
int main()
{
shared_ptr pa0(new AA("zqa")); // 初始化资源zqa。
shared_ptr pa1 = pa0; // 用已存在的shared_ptr拷贝构造,计数加1。
shared_ptr pa2 = pa0; // 用已存在的shared_ptr拷贝构造,计数加1。
cout << "pa0.use_count()=" << pa0.use_count() << endl; // 值为3。
shared_ptr pb0(new AA("zqb")); // 初始化资源zqb。
shared_ptr pb1 = pb0; // 用已存在的shared_ptr拷贝构造,计数加1。
cout << "pb0.use_count()=" << pb0.use_count() << endl; // 值为2。
pb1 = pa1; // 资源zqa的引用加1,资源zqb的引用减1。
pb0 = pa1; // 资源zqa的引用加1,资源zqb的引用成了0,将被释放。
cout << "pa0.use_count()=" << pa0.use_count() << endl; // 值为5。
cout << "pb0.use_count()=" << pb0.use_count() << endl; // 值为5。
}
在默认情况下,智能指针过期的时候,用delete原始指针; 释放它管理的资源。
程序员可以自定义删除器,改变智能指针释放资源的行为。
删除器可以是全局函数、仿函数和Lambda表达式,形参为原始指针。
示例:
#include
#include
using namespace std;
class AA
{
public:
string m_name;
AA() { cout << m_name << "调用构造函数AA()。\n"; }
AA(const string & name) : m_name(name) { cout << "调用构造函数AA("<< m_name << ")。\n"; }
~AA() { cout << "调用了析构函数~AA(" << m_name << ")。\n"; }
};
void deletefunc(AA* a) { // 删除器,普通函数。
cout << "自定义删除器(全局函数)。\n";
delete a;
}
struct deleteclass // 删除器,仿函数。
{
void operator()(AA* a) {
cout << "自定义删除器(仿函数)。\n";
delete a;
}
};
auto deleterlamb = [](AA* a) { // 删除器,Lambda表达式。
cout << "自定义删除器(Lambda)。\n";
delete a;
};
int main()
{
shared_ptr pa1(new AA("a"), deletefunc);
//shared_ptr pa2(new AA("b"), deleteclass());
//shared_ptr pa3(new AA("c"), deleterlamb);
//unique_ptr pu1(new AA("1"), deletefunc);
// unique_ptr pu0(new AA("1"), deletefunc);
//unique_ptr pu2(new AA("2"), deleteclass());
//unique_ptr pu3(new AA("3"), deleterlamb);
}