c/c++ 智能指针 shared_ptr 使用
程序员文章站
2023-08-21 08:13:29
智能指针 shared_ptr 使用 上一篇 "智能指针是啥玩意" ,介绍了什么是智能指针。 这一篇简单说说如何使用智能指针。 一,智能指针分3类:今天只唠唠shared_ptr shared_ptr unique_ptr weak_ptr 二,下表是shared_ptr和unique_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); */ }
五,智能指针的注意事项
把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; }