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

智能指针 shared_ptr 使用

上一篇智能指针是啥玩意,介绍了什么是智能指针。

这一篇简单说说如何使用智能指针。

一,智能指针分3类:今天只唠唠shared_ptr

  • shared_ptr
  • unique_ptr
  • weak_ptr

二,下表是shared_ptr和unique_ptr都支持的操作

操作 功能描述
shared_ptr<T> sp 空智能指针,可以指向类型为T的对象
unique_ptr<T> up 空智能指针,可以指向类型为T的对象
p 将p用作一个条件判断,如果p指向一个对象,则为true
*p 解引用p,获得它指向的对象
p->mem 等价于(*p).mem,访问p所指对象的mem成员
p.get() 返回p中保存的指针。如果指向的对象已经被释放,就是一个危险的指针
swap(p, q)或者p.swap(q) 交换p和q中的指针

上面操作的验证代码

  1. #include <memory>
  2. #include <iostream>
  3. #include <vector>
  4. using namespace std;
  5. class Test{
  6. public:
  7. Test(int d = 0):data(d){cout << "cr:" << data << endl;}
  8. ~Test(){cout << "fr:" << data << endl;}
  9. void fun(){
  10. cout << "Test func(" << data << ")" << endl;
  11. }
  12. private:
  13. int data;
  14. };
  15. int main(){
  16. //shared_ptr<Test> sp = make_shared<Test>();
  17. Test* pt = new Test();
  18. shared_ptr<Test> sp(pt);
  19. if(sp){
  20. cout << "sp指向了对象" << endl;
  21. }
  22. (*sp).fun();
  23. shared_ptr<int> isp;
  24. if(!isp){
  25. cout << "isp没有指向对象" << endl;
  26. }
  27. Test* tmp1 = sp.get();
  28. auto sp1 = make_shared<Test>(10);
  29. Test* tmp2 = sp1.get();
  30. swap(sp, sp1);
  31. tmp1->fun();//0
  32. tmp2->fun();//10
  33. //sp和sp1所指向的对象被交换了
  34. sp.get()->fun();//10
  35. sp1.get()->fun();//0
  36. }

三,下表是shared_ptr独有的操作

操作 功能描述
make_shared<T>(args) 返回shared_ptr,指向一个动态分配的类型为T的对象。使用args初始化此对象。
shared_ptr p是q的拷贝;递增q中的计数器。q中的指针必须能转化成T*。
p = q p和q都是shared_ptr,所保存的指针必须能相互转换。递减p的引用计数;递增q的引用计数;如果p的引用计数变为0,则释放p管理的对象的内存。
p.unique() 如果p.use_count()为1,则返回true;否则返回false
p.use_count() 返回与p共享对象的智能指针的数量;性能很低,用于调试。

上面操作的验证代码

  1. shared_ptr<Test> tsp = make_shared<Test>(11);
  2. cout << tsp.use_count() << endl;//1
  3. //tsp1和tsp指向相同的对象,这个对象的计数器加1
  4. shared_ptr<Test> tsp1(tsp);
  5. cout << tsp.use_count() << endl;//2
  6. //用tsp1改变了对象的data的值,所以用tsp再访问这个对象,发现对象被改变了
  7. tsp1->setData(111);
  8. tsp->fun();//111
  9. shared_ptr<Test> q(new Test(20));
  10. cout << q.use_count() << endl;//1
  11. cout << tsp.use_count() << endl;//2
  12. //如果q不是智能指针,q指向的Test(20)这块内存就泄露了
  13. //q是智能指针,所以自动释放了Test(20)这块内存
  14. q = tsp;
  15. cout << q.use_count() << endl;//3
  16. cout << tsp.use_count() << endl;//3
  17. if(!q.unique()){
  18. cout << "不是只有一个智能指针指向了某个对象" << endl;
  19. }

四,智能指针作为函数的返回值

  1. shared_ptr<Test> hun(int d){
  2. return make_shared<Test>(d);
  3. }
  4. void use_hun1(int d){
  5. shared_ptr<Test> p = hun(d);
  6. p->fun();
  7. }//p离开作用域后,它指向的内存会被自动释放
  8. shared_ptr<Test> use_hun2(int d){
  9. shared_ptr<Test> p = hun(d);//计数器为1
  10. return p;//返回p时,计数器递增,为2
  11. }//离开作用域后,计数器递减,为1,因为不为0,所以不会释放

一到四的小例子:

  1. include <memory>
  2. #include <iostream>
  3. #include <vector>
  4. using namespace std;
  5. class Test{
  6. public:
  7. Test(int d = 0):data(d){cout << "cr:" << data << endl;}
  8. ~Test(){cout << "fr:" << data << endl;}
  9. void fun(){
  10. cout << "Test func(" << data << ")" << endl;
  11. }
  12. void setData(int d){
  13. data = d;
  14. }
  15. private:
  16. int data;
  17. };
  18. //test3 智能指针作为函数的返回值
  19. shared_ptr<Test> hun(int d){
  20. return make_shared<Test>(d);
  21. }
  22. void use_hun1(int d){
  23. shared_ptr<Test> p = hun(d);
  24. p->fun();
  25. }//p离开作用域后,它指向的内存会被自动释放
  26. shared_ptr<Test> use_hun2(int d){
  27. shared_ptr<Test> p = hun(d);//计数器为1
  28. return p;//返回p时,计数器递增,为2
  29. }//离开作用域后,计数器递减,为1,因为不为0,所以不会释放
  30. int main(){
  31. //test1 shared_ptr和unique_ptr都支持的操作
  32. /*
  33. //shared_ptr<Test> sp = make_shared<Test>();
  34. Test* pt = new Test();
  35. shared_ptr<Test> sp(pt);
  36. if(sp){
  37. cout << "sp指向了对象" << endl;
  38. }
  39. (*sp).fun();
  40. shared_ptr<int> isp;
  41. if(!isp){
  42. cout << "isp没有指向对象" << endl;
  43. }
  44. Test* tmp1 = sp.get();
  45. auto sp1 = make_shared<Test>(10);
  46. Test* tmp2 = sp1.get();
  47. swap(sp, sp1);
  48. tmp1->fun();
  49. tmp2->fun();
  50. sp.get()->fun();
  51. sp1.get()->fun();
  52. */
  53. //test2 shared_ptr独有的操作
  54. /*
  55. shared_ptr<Test> tsp = make_shared<Test>(11);
  56. cout << tsp.use_count() << endl;//1
  57. //tsp1和tsp指向相同的对象,这个对象的计数器加1
  58. shared_ptr<Test> tsp1(tsp);
  59. cout << tsp.use_count() << endl;//2
  60. //用tsp1改变了对象的data的值,所以用tsp再访问这个对象,发现对象被改变了
  61. tsp1->setData(111);
  62. tsp->fun();//111
  63. shared_ptr<Test> q(new Test(20));
  64. cout << q.use_count() << endl;//1
  65. cout << tsp.use_count() << endl;//2
  66. //如果q不是智能指针,q指向的Test(20)这块内存就泄露了
  67. //q是智能指针,所以自动释放了Test(20)这块内存
  68. q = tsp;
  69. cout << q.use_count() << endl;//3
  70. cout << tsp.use_count() << endl;//3
  71. if(!q.unique()){
  72. cout << "不是只有一个智能指针指向了某个对象" << endl;
  73. }
  74. */
  75. //test3 智能指针作为函数的返回值
  76. /*
  77. auto ap = use_hun2(22);
  78. ap->fun();
  79. use_hun1(33);
  80. */
  81. }

github完整代码

五,智能指针的注意事项

把shared_ptr放入容器中时,之后不再需要全部元素,只使用其中一部分的话,要用erase删除那些不再需要使用的shared_ptr。如果不erase那些不再需要使用的shared_ptr,shared_ptr就不会释放它指向的内存。

六,智能指针的小例子,让多个对象共享相同的状态。

  • 有个类shared_vector,里面有个shared_ptr,指向了一个vector,类shared_vector的对象a2拷贝a1时,实现a1和a2共享vector。
  • 类un_shared_vector没有使用shared_ptr,所以没有共享vector。
  1. include <iostream>
  2. #include <memory>
  3. #include <vector>
  4. #include <string>
  5. using namespace std;
  6. class shared_vector{
  7. public:
  8. typedef vector<string>::size_type size_type;
  9. shared_vector():data(make_shared<vector<string>>()){}
  10. shared_vector(initializer_list<string> il):
  11. data(make_shared<vector<string>>(il)){}
  12. size_type size()const{return data->size();}
  13. bool empty()const{return data->empty();}
  14. //尾部插入,删除元素
  15. void push_back(const string& s){data->push_back(s);}
  16. void pop_back(){data->pop_back();}
  17. //访问元素
  18. string& front(){return data->front();}
  19. string& back(){return data->back();}
  20. private:
  21. shared_ptr<vector<string>> data;
  22. };
  23. class un_shared_vector{
  24. public:
  25. typedef vector<string>::size_type size_type;
  26. un_shared_vector():data(vector<string>()){}
  27. un_shared_vector(initializer_list<string> il):data(il){}
  28. size_type size()const{return data.size();}
  29. bool empty()const{return data.empty();}
  30. //尾部插入,删除元素
  31. void push_back(const string& s){data.push_back(s);}
  32. void pop_back(){data.pop_back();}
  33. //访问元素
  34. string& front(){return data.front();}
  35. string& back(){return data.back();}
  36. private:
  37. vector<string> data;
  38. };
  39. int main(){
  40. shared_vector sv{"aa","bb"};
  41. shared_vector sv1(sv);
  42. //因为sv和sv1共享同一个vector,
  43. //所以通过sv改变vector后,通过sv1也发现了相同的改变
  44. sv.push_back("cc");
  45. cout << sv1.back() << endl;
  46. un_shared_vector usv{"11","22"};
  47. un_shared_vector usv1(usv);
  48. //因为usv和usv1不共享同一个vector,
  49. //所以通过usv改变vector后,usv1里面的vector没有跟着变化
  50. usv.push_back("33");
  51. cout << usv1.back() << endl;
  52. cout << usv.back() << endl;
  53. }

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号