九、 通用工具 ----smart Pointer(智能指针)---shared_ptr 指针

2 smart Pointer(智能指针)

c++11提供两大类型的只能指针:

  • class shared_ptr :共享式拥有
  • class unique_ptr: 独占式拥有

    1. 所有的智能指针被定义在头文件<memory>;
    2. 智能指针只能用来管理动态内存,即new分配的动态内存;

1 shared_ptr 指针

  1. 在其所指向的对象不再被需要之后,自动释放与对象相关的资源;
  2. shared_ptr有一个关联的计数器–引用计数,记录指向同一个对象的shared_ptr指针的数量;
  3. 当计数器计数为0,此对象自动释放【使用use_count()统计】;

1.1 使用shared_ptr

shared_ptr和unique_ptr公有的操作:

表达式效果
shared_ptr<T> sp / unique<T> up空智能指针,可以指向T的对象
p将p作为一个条件判断,若指向一个对象,则为true
*p解引用p,获得p指向的对象
p->mem等价于(*p).mem
p.get()返回p中保存的指针,要小心使用,若智能指针释放了其对象,则返回的指针是空的
p.swap(q ) / swap(p,q)交换 p,q的指针

shared_ptr独有的操作

表达式效果
make_shared<T>(args)返回一个shared_ptr,指向动态分配的t对象
shared_ptr<T>p(q)p是shared_ptr q的拷贝,操作会递增q的计数器,q的指针必须能转换成 T*
p =qp和q都是shared_ptr,此操作会递减p所指向对象计数器,增加q指向对象计数器 ,如果p所指对象计数器为0,释放内存
p.unique()若p.use_count()返回1,返回true,否则false
p.use_count()返回指向同一对象的智能指针的数量,速度慢,主要用于调试

例子:

shared_ptr<string> p(new string("hello"));

shared_ptr的接受一个指针的构造函数是explicit:

//from pointer (3)  
template <class U> explicit shared_ptr (U* p);

所以不能进行隐式转换:
也可以使用make_shared()函数模板

shared_ptr<string> p(new string("hello")); //ok
shared_ptr<string> p = make_shared<string>("hello");

shared_ptr<string> p = new string("hello"); //error

shared_ptr的赋值:

  • 先声明,在赋值新的指针,必须使用reset()
  • 使用另一个指针拷贝
shared_ptr<string> p;
//第一种
p = new string("hello");  // error 
p.reset(new string("hello"));  //ok
//----------------
//第二种
shared_ptr<string> q(new string("haha"));
p = q;//两个指针指向同一个对象,计数器加一

1.2 定义 一个deleter

shared_ptr的构造函数有这么一种形式:
1. 带有两个参数,一个是指针,另一个是deleter对象,用于释放所拥有对象的Deleter对象,是一个可调用对象;
2. 在对象最后一个拥有者销毁的时候,会调用这个deleter对象;

//with deleter (4)

template <class U, class D> shared_ptr (U* p, D del);
//空指针,
template <class D> shared_ptr (nullptr_t p, D del);

例子:

shared_ptr<string> p(newstring("hello"),[](string*s){cout<<"deleter: " << *s << endl; });
cout << *p << endl;

结果为:

hello
deleter: hello

1.3 对付array

1.3.1 shared_ptr创建数组对象指针

  1. shared_ptr提供的默认deleter调用的是delete,不是delete[]
  2. 这意味着只有shared_ptr拥有单一new对象,使用默认deleter才有效;

因此,使用shared_ptr创建一个动态数组,发生错误:

shared_ptr<int> p (new int[10]); //错误,但是能够编译

因此,
(1). 如果使用new[]一个数组对象,需要定义自己的deleter.
例如:

shared_ptr<int> p (new int[10],[](int* p){ delete[] p;});

(2).也可以使用为unique_ptr提供的辅助函数作为deleter,其内调delete[]:

shared_ptr<int> p (new int[10],default_delete<int[]>());

1.3.2 shared_ptr指针的数组类型的参数
  1. 在unique_ptr指针中,允许只传递对应的元素作为template实参;
  2. 但是shared_ptr指针不行
    例如:
//int 和 int[]都可以, unique_ptr
    unique_ptr<int>u1(new int[10]);
    unique_ptr<int[]>u2(new int[10]);
// 只有int可以 ,shared_ptr
    shared_ptr<int> p(new int[10]);
    shared_ptr<int[]> p(new int[10]); //报错,不能编译

对于unique_ptr,必须明确给定第二个template实参,指出deleter:

    unique_ptr<int,void(*)(int*)>  u(new int[10], [](int* s){delete[] s; });

1.4 误用shared pointer

必须确保某对象只被一组shared pointer拥有,

1.4.1 shared_ptr不要与普通指针混合使用

例如:

int * p = new int;
shared_ptr<int> sp1(p);
shared_ptr<int> sp2(p);//error

这里有两组智能指针拥有所有钱,两个智能指针在销毁的时候会递减引用计数,意味着资源会被释放两次,从而p指针变成空悬指针;


所以应该创建对象的时候直接设立智能指针:

shared_ptr<int> sp1(new int);
shared_ptr<int> sp2(sp1);  //ok
1.4.2 不要使用get初始化另一个智能指针或为智能指针赋值

例如:

shared_ptr<int> p(new int(42)); //引用计数为1
int * q = p.get(); //注意:使用时不能让他管理指针被释放
{//新程序块
//未定义,两个独立的共享指针指向同一个内存
shared_ptr<int>(q); //独立的,引用计数为1
}//程序结束,里面的指针引用计数为0,q被销毁


int f = *p;  //错误,p的内存已被销毁

1.5 shared_ptr所有操作

shared pointer的所有操作:
share pointer 所有操作1

share pointer 所有操作2

share pointer 所有操作3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值