c/c++ 智能指针 shared_ptr 使用

智能指针 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中的指针

上面操作的验证代码

#include <memory>
#include <iostream>
#include <vector>

using namespace std;

class Test{
public:
  Test(int d = 0):data(d){cout << "cr:" << data << endl;}
  ~Test(){cout << "fr:" << data << endl;}
  void fun(){
    cout << "Test func(" << data << ")" << endl;
  }
private:
  int data;
};
int main(){
  //shared_ptr<Test> sp = make_shared<Test>();
  Test* pt = new Test();
  shared_ptr<Test> sp(pt);
  if(sp){
    cout << "sp指向了对象" << endl;
  }
  (*sp).fun();
  shared_ptr<int> isp;
  if(!isp){
    cout << "isp没有指向对象" << endl;
  }
  Test* tmp1 = sp.get();
  auto sp1 = make_shared<Test>(10);
  Test* tmp2 = sp1.get();
  swap(sp, sp1);
  tmp1->fun();//0
  tmp2->fun();//10
  //sp和sp1所指向的对象被交换了
  sp.get()->fun();//10
  sp1.get()->fun();//0

}

三,下表是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共享对象的智能指针的数量;性能很低,用于调试。

上面操作的验证代码

  shared_ptr<Test> tsp = make_shared<Test>(11);
  cout << tsp.use_count() << endl;//1
  //tsp1和tsp指向相同的对象,这个对象的计数器加1
  shared_ptr<Test> tsp1(tsp);
  cout << tsp.use_count() << endl;//2
  //用tsp1改变了对象的data的值,所以用tsp再访问这个对象,发现对象被改变了
  tsp1->setData(111);
  tsp->fun();//111                                                              

  shared_ptr<Test> q(new Test(20));
  cout << q.use_count() << endl;//1
  cout << tsp.use_count() << endl;//2
  //如果q不是智能指针,q指向的Test(20)这块内存就泄露了
  //q是智能指针,所以自动释放了Test(20)这块内存
  q = tsp;
  cout << q.use_count() << endl;//3
  cout << tsp.use_count() << endl;//3
  if(!q.unique()){
    cout << "不是只有一个智能指针指向了某个对象" << endl;
  }

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

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

一到四的小例子:

include <memory>
#include <iostream>
#include <vector>

using namespace std;

class Test{
public:
  Test(int d = 0):data(d){cout << "cr:" << data << endl;}
  ~Test(){cout << "fr:" << data << endl;}
  void fun(){
    cout << "Test func(" << data << ")" << endl;
  }
  void setData(int d){
    data = d;
  }
private:
  int data;
};

//test3 智能指针作为函数的返回值
shared_ptr<Test> hun(int d){
  return make_shared<Test>(d);
}
void use_hun1(int d){
  shared_ptr<Test> p = hun(d);
  p->fun();
}//p离开作用域后,它指向的内存会被自动释放
shared_ptr<Test> use_hun2(int d){
  shared_ptr<Test> p = hun(d);//计数器为1
  return p;//返回p时,计数器递增,为2
}//离开作用域后,计数器递减,为1,因为不为0,所以不会释放
int main(){
  //test1 shared_ptr和unique_ptr都支持的操作
  /*
  //shared_ptr<Test> sp = make_shared<Test>();
  Test* pt = new Test();
  shared_ptr<Test> sp(pt);
  if(sp){
    cout << "sp指向了对象" << endl;
  }
  (*sp).fun();
  shared_ptr<int> isp;
  if(!isp){
    cout << "isp没有指向对象" << endl;
  }
  Test* tmp1 = sp.get();
  auto sp1 = make_shared<Test>(10);
  Test* tmp2 = sp1.get();
  swap(sp, sp1);
  tmp1->fun();
  tmp2->fun();
  sp.get()->fun();
  sp1.get()->fun();
  */

  //test2 shared_ptr独有的操作
  /*
  shared_ptr<Test> tsp = make_shared<Test>(11);
  cout << tsp.use_count() << endl;//1
  //tsp1和tsp指向相同的对象,这个对象的计数器加1
  shared_ptr<Test> tsp1(tsp);
  cout << tsp.use_count() << endl;//2
  //用tsp1改变了对象的data的值,所以用tsp再访问这个对象,发现对象被改变了
  tsp1->setData(111);
  tsp->fun();//111                                                              

  shared_ptr<Test> q(new Test(20));
  cout << q.use_count() << endl;//1
  cout << tsp.use_count() << endl;//2
  //如果q不是智能指针,q指向的Test(20)这块内存就泄露了
  //q是智能指针,所以自动释放了Test(20)这块内存
  q = tsp;
  cout << q.use_count() << endl;//3
  cout << tsp.use_count() << endl;//3
  if(!q.unique()){
    cout << "不是只有一个智能指针指向了某个对象" << endl;
  }
  */

  //test3 智能指针作为函数的返回值
  /*
  auto ap = use_hun2(22);
  ap->fun();
  use_hun1(33);
  */

}

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。
include <iostream>
#include <memory>
#include <vector>
#include <string>

using namespace std;

class shared_vector{
public:
  typedef vector<string>::size_type size_type;
  shared_vector():data(make_shared<vector<string>>()){}
  shared_vector(initializer_list<string> il):
    data(make_shared<vector<string>>(il)){}
  size_type size()const{return data->size();}
  bool empty()const{return data->empty();}
  //尾部插入,删除元素
  void push_back(const string& s){data->push_back(s);}
  void pop_back(){data->pop_back();}
  //访问元素
  string& front(){return data->front();}
  string& back(){return data->back();}

private:
  shared_ptr<vector<string>> data;
};

class un_shared_vector{
public:
  typedef vector<string>::size_type size_type;
  un_shared_vector():data(vector<string>()){}
  un_shared_vector(initializer_list<string> il):data(il){}
  size_type size()const{return data.size();}
  bool empty()const{return data.empty();}
  //尾部插入,删除元素
  void push_back(const string& s){data.push_back(s);}
  void pop_back(){data.pop_back();}
  //访问元素
  string& front(){return data.front();}
  string& back(){return data.back();}

private:
  vector<string> data;
};

int main(){
  shared_vector sv{"aa","bb"};
  shared_vector sv1(sv);
  //因为sv和sv1共享同一个vector,
  //所以通过sv改变vector后,通过sv1也发现了相同的改变
  sv.push_back("cc");
  cout << sv1.back() << endl;

  un_shared_vector usv{"11","22"};
  un_shared_vector usv1(usv);
  //因为usv和usv1不共享同一个vector,
  //所以通过usv改变vector后,usv1里面的vector没有跟着变化
  usv.push_back("33");
  cout << usv1.back() << endl;
  cout << usv.back() << endl;
}

github完整代码

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

本人微信:xiaoshitou5854

原文地址:https://www.cnblogs.com/xiaoshiwang/p/9711169.html

时间: 2024-11-05 10:40:29

c/c++ 智能指针 shared_ptr 使用的相关文章

C++智能指针 shared_ptr

C++智能指针 shared_ptr shared_ptr 是一个标准的共享所有权的智能指针, 允许多个指针指向同一个对象. 定义在 memory 文件中(非memory.h), 命名空间为 std. shared_ptr 是为了解决 auto_ptr 在对象所有权上的局限性(auto_ptr 是独占的), 在使用引用计数的机制上提供了可以共享所有权的智能指针, 当然这需要额外的开销: (1) shared_ptr 对象除了包括一个所拥有对象的指针外, 还必须包括一个引用计数代理对象的指针. (

C/C++之智能指针shared_ptr

1.定义 shared_ptr的作用有如同指针,但会记录有多少个shared_ptrs共同指向一个对象.这便是所谓的引用计数(reference counting).一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除.这在非环形数据结构中防止资源泄露很有帮助. auto_ptr由于它的破坏性复制语义,无法满足标准容器对元素的要求,因而不能放在标准容器中:如果我们希望当容器析构时能自动把它容纳的指针元素所指的对象删除时,通常采用一些间接的方式来实现,显得比较繁琐

【C++】智能指针shared_ptr 定位删除器(仿函数)

智能指针shared_ptr 用引用计数实现看起来不错,但却存在问题. 1.引用计数更新存在着线程安全: 2.循环引用--使用一个弱引用智能指针(weak_ptr)来打破循环引用(weak_ptr不增加引用计数) 3.定置删除器和空间分配器 比如打开一个文件的关闭,用malloc开辟出来的空间,用引用计数实现会出现问题. 对改变引用计数时加锁可以解决引用计数更新存在着线程安全. 循环引用问题 #include<iostream> using namespace std; #include<

智能指针 shared_ptr 解析

最近正在进行<Effective C++>的第二遍阅读,书里面多个条款涉及到了shared_ptr智能指针,介绍的太分散,学习起来麻烦,写篇blog整理一下. LinJM   @HQU shared_ptr是一个智能指针.在C++ 11颁布之前,它包含在TR1(Technical Report 1)当中,现在囊括在C++11的标准库中. 智能指针 智能指针(Smart pointers)是存储"指向动态分配(在堆上)的对象的指针"的对象.也就是说,智能指针其实是个对象.不过

智能指针——shared_ptr

boost::scoped_ptr虽然简单易用,但它不能共享所有权的特性却大大限制了其使用范围,而boost::shared_ptr可以解决这一局限.顾名思义,boost::shared_ptr是可以共享所有权的智能指针 boost::shared_ptr的管理机制其实并不复杂,就是对所管理的对象进行了引用计数,当新增一个boost::shared_ptr对该对象进行管理时,就将该对象的引用计数加一:减少一个boost::shared_ptr对该对象进行管理时,就将该对象的引用计数减一,如果该对

Boost库中的智能指针 shared_ptr智能指针

shared_ptr智能指针的意思即:boost::shared_ptr是可以智能的管理动态分配的内存资源,几个智能指针可以同时共享一个动态分配的内存的所有权. 下面我们通过一个例子来学习一下它的用法: 注 :使用shared_ptr智能指针,要加入#include <boost/shared_ptr.hpp>头文件 class example { public: ~example() { std::cout <<"It's over\n"; } void do

Boost智能指针——shared_ptr

转: http://www.cnblogs.com/TianFang/archive/2008/09/19/1294521.html boost::scoped_ptr虽然简单易用,但它不能共享所有权的特性却大大限制了其使用范围,而boost::shared_ptr可以解决这一局限.顾名思义,boost::shared_ptr是可以共享所有权的智能指针,首先让我们通过一个例子看看它的基本用法: #include <string> #include <iostream> #inclu

C++智能指针shared_ptr

shared_ptr 这里有一个你在标准库中找不到的—引用数智能指针.大部分人都应当有过使用智能指针的经历,并且已经有很多关于引用数的文章.最重要的一个细节是引用数是如何被执行的—插入,意思是说你将引用计数的功能添加给类,或者是非插入,意思是说你不这样做.Boost shared_ptr是非插入类型的,这个实现使用一个从堆中分配来的引用计数器.关于提供参数化策略使得对任何情况都极为适合的讨论很多了,但是最终讨论的结果是决定反对聚焦于可用性.可是不要指望讨论的结果能够结束. shared_ptr完

深入剖析智能指针 shared_ptr

在effective C++经常会提到智能指针,这里对shared_ptr进行一个总结: 1 简要介绍用法 智能指针主要是用于资源管理,当申请一个资源的时候为了保证在离开控制流的时候对应资源应该得到相应的释放,这个时候如果资源对应一个类,在构造类的时候进行资源的分配(也就是书中经常提到的Resource Acquisition  Is Initialization RAII),在对象离开作用域的时候调用对应的析构函数资源得到适当的释放 这里有几个智能指针得到应用: auto_ptr: 被销毁的时