经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C » 查看文章
c/c++ 智能指针 shared_ptr 和 new结合使用
来源:cnblogs  作者:小石王  时间:2018/9/28 16:57:23  对本文有异议

智能指针 shared_ptr 和 new结合使用

用make_shared函数初始化shared_ptr是最推荐的,但有的时候还是需要用new关键字来初始化shared_ptr。

一,先来个表格,唠唠new和shared_ptr

操作 功能描述
shared_ptr<T> p(q) 智能指针p管理内置指针q所指向的对象;q必须指向new分配的内存,且能够转换为T*。
shared_ptr<T> p(u) p从unique_ptr u那里接管了原来u所指向对象的所有权,并将u置为空。
shared_ptr<T> p(q, d) p接管了内置指针q所指的对象的所有权。q必须能转换为T*。p将使用可调用对象d来代替delete。
p.reset() 如果p是唯一指向其对象的shared_ptr,reset会释放此对象。如果没传参数q,将p置为空。
p.reset(q) 如果传递了内置指针q,会让p指向q所指向的对象,否则会将p置为空。
p.reset(q, d) 如果还传递了参数d,将会调用d,而不是delete来释放q

二,智能指针和普通指针一起使用的陷阱

  1. void pro(shared_ptr<int> ptr){
  2. }
  3. shared_ptr<int> p(new int(42));//计数器为1
  4. pro(p);//p作为参数会进行copy递增它的计数器,在pro内部计数器是2
  5. int i = *p;//计数器为1
  6. cout << i << endl;
  7. int* bad = new int(11);
  8. //pro(bad);//编译错误
  9. pro(shared_ptr<int>(bad));//合法,但出了pro,bad所指向的内存会被释放
  10. int j = *bad;//解指针bad就会产生难以预料的结果

三,也不要使用get初始化另一个智能指针或为智能指针赋值

  1. shared_ptr<int> p(new int(12));
  2. int* q = p.get();
  3. {
  4. shared_ptr<int> tmp(q);
  5. }//程序块结束后,q所指向的对象被释放
  6. int f = *p;//解指针p就会产生难以预料的结果
  7. cout << f << endl;

四,智能指针和异常

  1. void f(){
  2. shared_ptr<int> sp(new int(11));
  3. //假设抛出了异常,而且在f中未捕获
  4. }//函数结束后shared_ptr自动释放内存
  5. void f1(){
  6. int* ip = new int(12);
  7. //假设delete语句前抛出了异常,而且在f中未捕获
  8. delete ip;
  9. }//函数结束后ip所指向的内存没有被释放。

五,智能指针使用的最佳建议

  • 不使用相同的内置指针初始化(或reset)多个智能指针。
  • 不使用get()初始化或reset另一个智能指针。
  • 不delete get()返回的指针。
  • 如果使用了get()返回的指针,请牢记,当最后一个对应的智能指针被销毁后,你的指针就变为无效了。
  • 如果使用智能指针管理的资源不是new分配的内存,请传递给它一个删除器。

小例子:

  1. #include <iostream>
  2. #include <memory>
  3. #include <vector>
  4. using namespace std;
  5. class Test{
  6. public:
  7. Test(int d = 0) : data(d){cout << "new:" << data << endl;}
  8. ~Test(){cout << "del:" << data << endl;}
  9. private:
  10. int data;
  11. };
  12. void my_deleter(Test* t){
  13. cout << "my_deleter is work" << endl;
  14. }
  15. void pro(shared_ptr<int> ptr){
  16. }
  17. int main(){
  18. //test1 reset
  19. /*
  20. Test* tp = new Test(1);
  21. shared_ptr<Test> stp(tp);
  22. shared_ptr<Test> stp1(stp);
  23. stp.reset();
  24. cout << stp << endl;
  25. */
  26. //test2 自定义删除器
  27. /*
  28. Test* tp = new Test(1);
  29. //不会调用Test的析构函数了,只调用my_deleter函数
  30. shared_ptr<Test> stp(tp, my_deleter);
  31. shared_ptr<Test> stp1(stp);
  32. cout << stp.use_count() << endl;
  33. Test* tp1 = new Test(2);
  34. stp1.reset(tp1, my_deleter);
  35. */
  36. //test3 不要混用普通指针和智能指针
  37. /*
  38. shared_ptr<int> p(new int(42));//计数器为1
  39. pro(p);//p作为参数会进行copy递增它的计数器,在pro内部计数器是2
  40. int i = *p;//计数器为1
  41. cout << i << endl;
  42. int* bad = new int(11);
  43. //pro(bad);//编译错误
  44. pro(shared_ptr<int>(bad));//合法,但出了pro,bad所指向的内存会被释放
  45. int j = *bad;//解指针bad就会产生难以预料的结果
  46. */
  47. //test4 get的错误使用
  48. /*
  49. shared_ptr<int> p(new int(12));
  50. int* q = p.get();
  51. {
  52. shared_ptr<int> tmp(q);
  53. }//程序块结束后,q所指向的对象被释放
  54. int f = *p;//解指针p就会产生难以预料的结果
  55. cout << f << endl;
  56. */
  57. }

github完整代码

c/c++ 学习互助QQ群:877684253

本人微信:xiaoshitou5854

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号