九、 通用工具 ----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

智能指针是C++中用于管理动态分配的内存的一种机制。它们可以自动地在不再需要时释放内存,从而避免内存泄漏和悬挂指针的问题。 shared_ptr是一种引用计数智能指针,它可以跟踪有多少个shared_ptr指向同一个对象,并在没有引用时自动释放内存。当创建shared_ptr时,它会增加引用计数,当销毁或重置shared_ptr时,它会减少引用计数。只有当引用计数为0时,才会真正释放内存。\[1\]shared_ptr可以通过构造函数接受一个指向动态分配对象的指针来创建,也可以使用std::make_shared函数来创建。\[2\] unique_ptr是一种独占智能指针,它拥有对动态分配对象的唯一所有权。当unique_ptr被销毁时,它会自动释放内存。unique_ptr不能被复制,但可以通过std::move函数进行转移所有权。\[3\]unique_ptr可以通过构造函数接受一个指向动态分配对象的指针来创建。 weak_ptr是一种弱引用智能指针,它指向由shared_ptr管理的对象,但不会增加引用计数。weak_ptr可以用于解决shared_ptr的循环引用问题,因为它不会导致对象无法释放。\[1\]weak_ptr可以通过shared_ptr的构造函数来创建。 auto_ptr是C++11之前的一种智能指针,它类似于unique_ptr,但有一些限制和问题。auto_ptr在复制时会转移所有权,这可能导致悬挂指针的问题。因此,auto_ptr已经被unique_ptr取代,不推荐使用。 总结来说,shared_ptr是引用计数智能指针,unique_ptr是独占智能指针,weak_ptr是弱引用智能指针,而auto_ptr是已经过时的智能指针。它们各自有不同的用途和特点,可以根据具体的需求选择使用。 #### 引用[.reference_title] - *1* *2* *3* [C++11 解决内存泄露问题的智能指针shared_ptr、unique_ptr、weak_ptr](https://blog.csdn.net/weixin_44120785/article/details/128714630)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值