<C++学习篇>C++中的智能指针auto_ptr,unique_otr,shared_ptr
来源:互联网 发布:算法视频教程 编辑:程序博客网 时间:2024/06/06 10:38
在C++中为了更好的管理动态内存,C++98~C++11引入智能指针 auto_ptr,unique_otr,shared_ptr
与常规指针相比,智能指针在过期之后会自动销毁所分配的内存空间.
提到内存空间,有一些概念:
例如:
引用网上的解释 :
int a=0;//全局初始化区char *p;//全局未初始化区int main(){int b;//栈char s[]="abc";//栈char *p2;//栈char *p3="123456";//p3在栈,"123456"在常量区static int c=0;//全局初始化区p1=(char*)malloc(10);//分配的内存在堆区return 0;}
再看代码
void remodel(std::string & str){ std::string *ps=new std::string(str);//这里new 分配出来的内存在堆上 ... str=ps; return ;//函数执行到这里,指针ps保存的地址值被清掉,地址所指的堆内存却未处理,导致内存泄露 //应该在return之前加上 delete ps;语句}
这段代码,我们自己new开辟的内存还要自己手动释放,但很多时候,忘了,导致内存泄露
引入智能指针,就是避免了我们忘记释放内存而导致内存泄露
智能指针其实是个类对象,只是行为类似指针
使用智能指针要包含头文件:
#include<memory>
- auto_ptr
- shared_ptr
- unique_ptr
//auto_ptr.cpp#include<iostream>#include<memory>#include<string>class Report{ private: std::string str; public: Report(const std::string s):str(s) {std::cout<<"Object be created!";} ~Report(){std::cout<<"Object deleted!";} void comment() const {std::cout<<str<<"\n";}};int main(){ { std::auto_ptr<Report>ps (new Report("using auto_ptr")); ps->comment(); }//ps 有效期就在这个代码块里,出了该范围就过期,auto_ptr帮我们自动销毁ps所指内存 { std::shared_ptr<Report>ps (new Report("using shared_ptr")); ps->comment(); }//ps 有效期就在这个代码块里,出了该范围就过期,shared_ptr帮我们自动销毁ps所指内存 { std::unique_ptr<Report>ps (new Report("using unique_ptr")); ps->comment(); }//ps 有效期就在这个代码块里,出了该范围就过期,unique_ptr帮我们自动销毁ps所指内存return 0;}
输出结果:
Object created!
using auto_ptr
Object delete!
Object created!
using shared_ptr
Object delete!
Object created!
using unique_ptr
Object delete!
但c++11中 auto_ptr被摒弃,因为auto_ptr同类指针之间相互赋值,产生了空指针,使用空指针,会导致问题!(也有说,两个指针指向同一个对象,智能指针释放内存空间时,该空间被连续释放两次)
代码如下:
auto_ptr<string>ps (new string(" 哈哈哈哈"));auto_ptr<string> ps1;ps1=ps;//ps 失去新建对象的所有权,ps指的对象被ps1剥夺,ps变成空指针,ps1 指向new 出来的"哈哈哈哈"std::cout<<ps<<"\n";//再次使用到ps指针时会报异常,Sementation 11(g++ 编译得出))
给出C++ primer plus上的源代码
//fowl.cpp -- auto_ptr a poor choice #include<iostream>#include<string>#include<memory>int main(){ using namespace std; auto_ptr<string> films[5]= { auto_ptr<string>(new string("Fowl Balls")), auto_ptr<string>(new string("Duck Walks")), auto_ptr<string>(new string("Chicken Runs")), auto_ptr<string>(new string("Turkey Errors")), auto_ptr<string>(new string("Goose Eggs")) }; auto_ptr<string> pwin; pwin=films[2];//films[2]失去对"chicken runs" 所有权 cout<<"The nominees for best avian baseball film are \n"; for(int i=0;i<5;i++) cout<<*films[i]<<endl;//当然了,当i=2 ,循环停止,因为会报异常:Sementation 11(具体因系统而异) ,因为films[2] 变成空指针了 cout<<"The winner is :"<<*pwin<<"!\n"; cin.get(); return 0;}
运行报错:
将auto_ptr改为shared_ptr
运行ok:
因为使用shared_ptr 后pwin和films[2]指向的是同一个对象,引用计数变为2,pwin调用后销毁,计数变为1,films[2]数组再次调用销毁,计数变为0,空间真正被释放
那么换为uinque_ptr会怎样?
直接会在编译是报错,
unique_ptr比auto_ptr 更安全
unique_ptr 指的是一个对象,只能有一个智能指针拥有它(空间和时间上).该指针会在编译阶段判断,有异常不会在运行阶段爆发,所以说更安全
特别指出的是,如果有一个智能指针所指的对象,在该对象赋给另一个智能指针时,前一个智能指针已经被销毁,那么也是可以的,例如:
unique_ptr<string> demo(string &str){ unique_ptr<string> temp (new string(str)); return temp;}unique_ptr<string> ps;ps=demo("UNIQUE_PTR TEST");//demo() 返回一个临时unique_ptr ,然后ps剥夺temp 指针所指的对象所有权,随后temp被销毁,不复存在,没有机会使用它访问无效数据,这就是时间上允许两个指针都指向同一对象.若是temp会和ps共存一段时间,那么是不被允许的例如:unique_ptr<string>temp(new string("Hi ho!"));unique_ptr<string>ps;ps=temp;//不被允许,temp(剥夺所有权后为空指针)会同时存在一段时间,有可能会被使用//可以使用std::move()更改,okunique_ptr<string> ps1;ps1=unique_ptr<string>(new string("hah")));//允许, 调用unique_ptr<string>构造函数创建一个临时变量,被剥夺所有权后被销毁ps=temp;//不被允许,temp(剥夺所有权后为空指针)会同时存在一段时间,有可能会被使用但可以使用std::move()更改,ok ps=move(temp);
更改前面代码:
int main(){ using namespace std; unique_ptr<string> films[5]= { unique_ptr<string>(new string("Fowl Balls")), unique_ptr<string>(new string("Duck Walks")), unique_ptr<string>(new string("Chicken Runs")), unique_ptr<string>(new string("Turkey Errors")), unique_ptr<string>(new string("Goose Eggs")) }; unique_ptr<string> pwin; pwin=move(films[2]);//films[2]失去对"chicken runs" 所有权 cout<<"The nominees for best avian baseball film are \n"; for(int i=0;i<5;i++) { if(i==2) continue;//当i=2 ,循环停止,因为会报异常:Sementation 11(具体因系统而异) ,因为films[2] 变成空指针,所以我用continue语句跳过i=2,从i=3处执行,这样就OK cout<<*films[i]<<endl; } cout<<"The winner is :"<<*pwin<<"!\n"; cin.get(); return 0;}
结果:
auto_ptr 智能指针不能自动销毁new 出来的数字
eg
int main(){ using namespace std; double *pd=new double; *pd=1.222; unique_ptr<double> spd(pd);//ok double *pd1=new double[11]{9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,4.0}; for(int i=0;i<9;i++) cout<<"pd1["<<i<<"] = "<<pd1[i]<<endl; // delete[] pd1; return 0;}
运行如下:
未delete[]pd1,堆内存未被回收
修改如下:
int main(){ using namespace std; double *pd=new double; *pd=1.222; unique_ptr<double> spd(pd);//ok double *pd1=new double[11]{9.0,9.0,9.0,9.0,9.0,9.0,9.0,9.0,4.0}; { unique_ptr<double[]> spd1(pd1); } for(int i=0;i<9;i++) cout<<"pd1["<<i<<"] = "<<pd1[i]<<endl; // delete[] pd1; return 0;}
运行:
可见,内存被销毁了!
最后说的是:
使用new 分配内存时,才能使用auto_ptr,shared_ptr,不是new分配的内存,不能使用,而使用new[],可以使用unique_ptr
- <C++学习篇>C++中的智能指针auto_ptr,unique_otr,shared_ptr
- 【C++】智能指针auto_ptr/unique_ptr/shared_ptr/weak_ptr!!!
- 【C++】智能指针auto_ptr
- C++中的智能指针auto_ptr,shared_ptr
- c++ auto_ptr智能指针详解
- 智能指针:auto_ptr和shared_ptr
- 智能指针(auto_ptr 和 shared_ptr)
- 智能指针(auto_ptr 和 shared_ptr)
- 智能指针(auto_ptr 和 shared_ptr)
- 智能指针(auto_ptr 和 shared_ptr)
- 智能指针(auto_ptr 和 shared_ptr)
- 智能指针(auto_ptr 和 shared_ptr)
- 智能指针(auto_ptr 和 shared_ptr)
- 智能指针(auto_ptr 和 shared_ptr)
- 智能指针(auto_ptr 和 shared_ptr)
- c++智能指针:auto_ptr shared_ptr
- c++智能指针:auto_ptr shared_ptr
- C++:智能指针之shared_ptr
- CSS盒子模型
- Android Bitmap面面观
- JVM学习笔记(四)------内存调优
- 自己写bootloader1 - start.S,基于s3c2440
- 你应该知道的那些Android小经验
- <C++学习篇>C++中的智能指针auto_ptr,unique_otr,shared_ptr
- apache服务器配置虚拟主机,使用自己的域名
- dataTable的当前页面刷新draw操作
- hihocoder1459 震荡数组
- 漫步微积分三十六——曲面的面积
- Sql Server 2008——查询(3)——IN的用法
- ubuntu14常见问题解决
- OAuth 2.0 教程
- 自己写bootloader2 -跳转执行,基于s3c2440