[C++11] 智能指针
c++智能指针介绍
由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete,比如流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 delete 的情况并不罕见,并造成内存泄露。如此c++引入智能指针 ,智能指针即是C++ RAII的一种应用,可用于动态资源管理,资源即对象的管理策略。 智能指针在 <memory> 标头文件的 std 命名空间中定义。 它们对 RAII 或获取资源即初始化编程惯用法至关重要。RAII 的主要原则是为所有堆分配资源提供所有权,例如动态分配内存或系统对象句柄、析构函数包含要删除或释放资源的代码的堆栈分配对象,以及任何相关清理代码。
c++智能指针类别
c++ 智能指针主要包括:unique_ptr,shared_ptr, weak_ptr, 这三种,其中auto_ptr 已被遗弃。
(1) shared_ptr
采用引用计数的智能指针。 shared_ptr基于“引用计数”模型实现,多个shared_ptr可指向同一个动态对象,并维护了一个共享的引用计数器,记录了引用同一对象的shared_ptr实例的数量。当最后一个指向动态对象的shared_ptr销毁时,会自动销毁其所指对象(通过delete操作符)。shared_ptr的默认能力是管理动态内存,但支持自定义的Deleter以实现个性化的资源释放动作。头文件:<memory>。
创建方式如下:
shared_ptr<int> p1 = make_shared<int>(1);// 通过make_shared函数shared_ptr<int> p2(new int(2));// 通过原生指针构造
(2)weak_ptr
结合 shared_ptr 使用的特例智能指针。 weak_ptr 提供对一个或多个 shared_ptr 实例所属对象的访问,但是,不参与引用计数。 如果您想要观察对象但不需要其保持活动状态,请使用该实例。 在某些情况下需要断开 shared_ptr 实例间的循环引用。 头文件:<memory>。
(3)unique_ptr
只允许基础指针的一个所有者。 可以移到新所有者(具有移动语义),但不会复制或共享(即我们无法得到指向同一个对象的两个unique_ptr)。 替换已弃用的 auto_ptr。 相较于 boost::scoped_ptr。 unique_ptr 小巧高效;大小等同于一个指针,支持 rvalue 引用,从而可实现快速插入和对 STL 集合的检索。 头文件:<memory>。
注意事项
(1)share_ptr循环引用
#include <iostream>
#include <memory>
using namespace std;class B;
class A
{
public:// 为了省去一些步骤这里 数据成员也声明为public//weak_ptr<B> pb;shared_ptr<B> pb;void doSomthing(){
// if(pb.lock())
// {
//
// }}~A(){cout << "kill A\n";}
};class B
{
public://weak_ptr<A> pa;shared_ptr<A> pa;~B(){cout <<"kill B\n";}
};int main(int argc, char** argv)
{shared_ptr<A> sa(new A());shared_ptr<B> sb(new B());if(sa && sb){sa->pb=sb;sb->pa=sa;}cout<<"sa use count:"<<sa.use_count()<<endl;return 0;
}
上面的代码运行结果为:sa use count:2, 注意此时sa,sb都没有释放,产生了内存泄露问题!!!
即A内部有指向B,B内部有指向A,这样对于A,B必定是在A析构后B才析构,对于B,A必定是在B析构后才析构A,这就是循环引用问题,违反常规,导致内存泄露。
使用weak_ptr来打破循环引用
代码如下:
#include <iostream>
#include <memory>
using namespace std;class B;
class A
{
public:// 为了省去一些步骤这里 数据成员也声明为publicweak_ptr<B> pb;//shared_ptr<B> pb;void doSomthing(){shared_ptr<B> pp = pb.lock();if(pp)//通过lock()方法来判断它所管理的资源是否被释放{cout<<"sb use count:"<<pp.use_count()<<endl;}}~A(){cout << "kill A\n";}
};class B
{
public://weak_ptr<A> pa;shared_ptr<A> pa;~B(){cout <<"kill B\n";}
};int main(int argc, char** argv)
{shared_ptr<A> sa(new A());shared_ptr<B> sb(new B());if(sa && sb){sa->pb=sb;sb->pa=sa;}sa->doSomthing();cout<<"sb use count:"<<sb.use_count()<<endl;return 0;
}
参考:https://blog.51cto.com/11142019/1846847
(2)unique_ptr控制权转移问题
我们无法复制 unique_ptr 对象,但我们可以转移它们。这意味着 unique_ptr 对象可以将关联的原始指针的所有权转移到另一个 unique_ptr 对象。
// 通过原始指针创建 taskPtr2
std::unique_ptr<Task> taskPtr2(new Task(55));
// 把taskPtr2中关联指针的所有权转移给taskPtr4
std::unique_ptr<Task> taskPtr4 = std::move(taskPtr2);
// 现在taskPtr2关联的指针为空
if(taskPtr2 == nullptr)std::cout<<"taskPtr2 is empty"<<std::endl;// taskPtr2关联指针的所有权现在转移到了taskPtr4中
if(taskPtr4 != nullptr)std::cout<<"taskPtr4 is not empty"<<std::endl;// 会输出55
std::cout<< taskPtr4->mId << std::endl;
std::move()
将把 taskPtr2
转换为一个右值引用。因此,调用 unique_ptr 的移动构造函数,并将关联的原始指针传输到 taskPtr4
。在转移完原始指针的所有权后, taskPtr2
将变为空。
释放关联的原始指针
在 unique_ptr 对象上调用 release()
将释放其关联的原始指针的所有权,并返回原始指针。这里是释放所有权,并没有delete原始指针,reset()
会delete原始指针。
std::unique_ptr<Task> taskPtr5(new Task(55));
// 不为空
if(taskPtr5 != nullptr)std::cout<<"taskPtr5 is not empty"<<std::endl;
// 释放关联指针的所有权
Task * ptr = taskPtr5.release();
// 现在为空
if(taskPtr5 == nullptr)std::cout<<"taskPtr5 is empty"<<std::endl;
[C++11] 智能指针相关推荐
- 详解C++11智能指针
详解C++11智能指针 前言 C++里面的四个智能指针: auto_ptr, unique_ptr,shared_ptr, weak_ptr 其中后三个是C++11支持,并且第一个已经被C++11弃用 ...
- 【C++11新特性】 C++11智能指针之weak_ptr
http://blog.csdn.net/xiejingfa/article/details/50772571 原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/ar ...
- c++11新特性_【C++11新特性】 C++11智能指针之weak_ptr
如题,我们今天要讲的是 C++11 引入的三种智能指针中的:weak_ptr. 在学习 weak_ptr 之前最好对 shared_ptr 有所了解.如果你还不知道 shared_ptr 是何物,可以 ...
- C++11智能指针(unique_ptr、shared_ptr、weak_ptr)boost::scoped_ptr
C++11智能指针(unique_ptr.shared_ptr.weak_ptr)_-码农小非-的专栏-CSDN博客_c++ shared_ptr weak_ptr 原创)智能指针拾遗 (原创)智能指 ...
- C++11 智能指针时要避开的 10 大错误
我很喜欢C++11全新的智能指针,对于那些苦恼于自己管理内存的开发者来说,这是天大的好事.但是,在广泛使用C++11智能指针的两年里,因为使用方法不当而导致程序的效率下降甚至直接crash掉的事情发生 ...
- 使用 C++11 智能指针时要避开的 10 大错误
http://blog.jobbole.com/104666/ 我很喜欢新的C++11的智能指针.在很多时候,对很多讨厌自己管理内存的人来说是天赐的礼物.在我看来,C++11的智能指针能使得C++新手 ...
- 十大愚蠢的错误,以避免与C ++ 11智能指针
Top 10 dumb mistakes to avoid with C++ 11 smart pointers I love the new C++ 11 smart pointers. In ma ...
- c++11 智能指针 unique_ptr、shared_ptr与weak_ptr
C++11中有unique_ptr.shared_ptr与weak_ptr等智能指针(smart pointer),定义在<memory>中. 可以对动态资源进行管理,保证任何情况下,已构 ...
- 窥见C++11智能指针
导语: C++指针的内存管理相信是大部分C++入门程序员的梦魇,受到Boost的启发,C++11标准推出了智能指针,让我们从指针的内存管理中释放出来,几乎消灭所有new和delete.既然智能指针如此 ...
- 【C++11新特性】 C++11智能指针之shared_ptr
http://blog.csdn.net/Xiejingfa/article/details/50750037 原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/ar ...
最新文章
- All in one: pentest under metasploit
- Java 中的 BigDecimal 类你了解多少?
- 互联网1分钟 |1109
- Linux ln指令
- leetcode面试题 16.19. 水域大小(深度优先搜索)
- 为什么80%的码农都做不了架构师?
- matplotlib绘制极坐标图像
- 20162303 实验五 网络编程与安全
- 极简代码(二)—— 转置 list of lists
- load data file使用详解
- VFP开眼看世界的第一眼,就是学会真正的BS开发,走错一步费三年
- c51流水灯实验报告汇编语言,51单片机流水灯实验报告.doc
- HDU 4289 Control (最大流最小割)
- 信号与系统28(状态变量与状态方程)
- python实现函数的最佳平方逼近
- sqlite设密工具如何使用(本人资源)
- java输出美国的时间_java显示当前美国洛杉矶时间
- Linux内存管理之UMA模型和NUMA模型
- 多模态 跨模态|人机交互新突破!
- python连乘函数_(Python3) 连加 连乘 代码
热门文章
- C++11 static_assert
- 【李宏毅2020 ML/DL】P53-55 Conditional Generation by RNN Attention Pointer Network Recursive
- 修改telnet提示并非_iPhone修改微信提示音,iOS12可用,无需越狱详细教程
- 0e php若类型,0e开头MD5 python生成脚本 PHP哈希弱类型比较缺陷
- 在 Linux 的应用中测试中的延时和丢包模拟
- linux vim 粘贴 没有保持原来的格式,linux中的剪贴板用法,实现vim中原格式粘贴...
- [黑金原创教程][连载][iBoard 电子学堂][第〇卷 电子基础]第一篇 认识电子元器件...
- 基于JSP的数据库增删改查实现
- 使用GDAL构造OpenCV的图像格式
- ArcGIS——图形转要素(标注转注记后发布服务问题)