C++智能指针的使用
2016-06-16 19:15
260 查看
C++使用new在堆上动态分配内存,若程序员忘记回收内存即delete释放内存,在执行过程中会内存泄露。针对这种常见错误,C++98提出了auto_ptr,C++11摒弃了auto_ptr,提出了另外两种解决方案unique_ptr和shared_ptr。auto_ptr、unique_ptr和shared_ptr组成了3个智能指针模板类,它们都定义了类似指针的对象,可以将new获得的地址直接或间接的赋值给该对象。当智能指针过期时调用类的析构函数delete释放内存空间,从而实现辅助程序员以减少错误的功能。如下所示为C++primer中智能指针和常规指针在内存分配及释放过程中的比较示意图。
使用智能指针时,需包含<memory>头文件,使用auto_ptr需要编译器支持C++98,unique_ptr和shared_ptr需要编译器支持C++11。
智能指针的定义及初始化如下:
auto_ptr<int> p(new int);
unique_ptr<double> q(new double);
shared_ptr<long> r(new long);
3个智能指针都有显示构造函数,该构造函数将指针作为参数,所以不允许将指针自动转换为智能指针对象,如下例所示:
针对智能指针在复制传递过程中,存在两个指针指向同一块内存区域,有可能释放两次的问题,auto_ptr和unique_ptr提出了一种建立所有权的概念,对于特定的内存对象,只能有一个智能指针指向它,所以规定复制过程中转让所有权,只能由具有所有权的指针释放该对象内存。shared_ptr采用引用计数的方法,即在赋值过程中计数加1,而指针过期时计数减1,仅当最后一个指针过期时才使用delete释放内存。
auto_ptr<int> p(new int);
*p=10;
cout<<*p<<" "<<&p<<endl;
auto_ptr<int> q=p;
cout<<*q<<endl;
// cout<<*p<<endl;//Error...
以上代码中将p指针赋值给q,因此q获得p的所有权,再访问p指针时程序会出现错误,这也是C++11摒弃auto_ptr的原因。
shared_ptr<int> p(new int);
*p=10;
cout<<*p<<" "<<&p<<endl;
shared_ptr<int> q=p;
cout<<*q<<endl;
cout<<*p<<endl;//No Error...
采用shared_ptr即可解决以上问题,在赋值的过程中该对象的引用计数加1,两者都能访问该对象,同时在过期时引用计数依次减1,最后一个指针才释放内存。
使用unique_ptr不允许将指针复制,如下代码在编译过程中会报错,相比于auto_ptr中潜在的悬挂指针更安全。
unique_ptr<double> r(new double);
*r=9.78347;
cout<<*r<<endl;
unique_ptr<double> u(new double);
u=r;//Error
此外,相比于auto_ptr,unique_ptr还有另一个优点,它有一个可用于数组的变体:
unique_ptr<int []> a(new int(5));
for(int i=0;i<5;i++){
a[i]=100-i;
}
for(int j=0;j<5;j++){
cout<<a[j]<<endl;
}
unique_ptr指针a过期时会调用delete []来释放内存。
总结如下:使用new分配内存时,才能使用auto_ptr和shared_ptr,使用new[]分配内存时,不能使用它们。不使用new分配内存时不能使用auto_ptr和shared_ptr,不使用new和new[]时,不能使用unique_ptr。在选择智能指针时,若程序需要使用多个指针指向同一对象,需采用shared_ptr指针,否则,采用unique_ptr智能指针。
使用智能指针时,需包含<memory>头文件,使用auto_ptr需要编译器支持C++98,unique_ptr和shared_ptr需要编译器支持C++11。
智能指针的定义及初始化如下:
auto_ptr<int> p(new int);
unique_ptr<double> q(new double);
shared_ptr<long> r(new long);
3个智能指针都有显示构造函数,该构造函数将指针作为参数,所以不允许将指针自动转换为智能指针对象,如下例所示:
针对智能指针在复制传递过程中,存在两个指针指向同一块内存区域,有可能释放两次的问题,auto_ptr和unique_ptr提出了一种建立所有权的概念,对于特定的内存对象,只能有一个智能指针指向它,所以规定复制过程中转让所有权,只能由具有所有权的指针释放该对象内存。shared_ptr采用引用计数的方法,即在赋值过程中计数加1,而指针过期时计数减1,仅当最后一个指针过期时才使用delete释放内存。
auto_ptr<int> p(new int);
*p=10;
cout<<*p<<" "<<&p<<endl;
auto_ptr<int> q=p;
cout<<*q<<endl;
// cout<<*p<<endl;//Error...
以上代码中将p指针赋值给q,因此q获得p的所有权,再访问p指针时程序会出现错误,这也是C++11摒弃auto_ptr的原因。
shared_ptr<int> p(new int);
*p=10;
cout<<*p<<" "<<&p<<endl;
shared_ptr<int> q=p;
cout<<*q<<endl;
cout<<*p<<endl;//No Error...
采用shared_ptr即可解决以上问题,在赋值的过程中该对象的引用计数加1,两者都能访问该对象,同时在过期时引用计数依次减1,最后一个指针才释放内存。
使用unique_ptr不允许将指针复制,如下代码在编译过程中会报错,相比于auto_ptr中潜在的悬挂指针更安全。
unique_ptr<double> r(new double);
*r=9.78347;
cout<<*r<<endl;
unique_ptr<double> u(new double);
u=r;//Error
此外,相比于auto_ptr,unique_ptr还有另一个优点,它有一个可用于数组的变体:
unique_ptr<int []> a(new int(5));
for(int i=0;i<5;i++){
a[i]=100-i;
}
for(int j=0;j<5;j++){
cout<<a[j]<<endl;
}
unique_ptr指针a过期时会调用delete []来释放内存。
总结如下:使用new分配内存时,才能使用auto_ptr和shared_ptr,使用new[]分配内存时,不能使用它们。不使用new分配内存时不能使用auto_ptr和shared_ptr,不使用new和new[]时,不能使用unique_ptr。在选择智能指针时,若程序需要使用多个指针指向同一对象,需采用shared_ptr指针,否则,采用unique_ptr智能指针。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解