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] 智能指针相关推荐

  1. 详解C++11智能指针

    详解C++11智能指针 前言 C++里面的四个智能指针: auto_ptr, unique_ptr,shared_ptr, weak_ptr 其中后三个是C++11支持,并且第一个已经被C++11弃用 ...

  2. 【C++11新特性】 C++11智能指针之weak_ptr

    http://blog.csdn.net/xiejingfa/article/details/50772571 原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/ar ...

  3. c++11新特性_【C++11新特性】 C++11智能指针之weak_ptr

    如题,我们今天要讲的是 C++11 引入的三种智能指针中的:weak_ptr. 在学习 weak_ptr 之前最好对 shared_ptr 有所了解.如果你还不知道 shared_ptr 是何物,可以 ...

  4. 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 原创)智能指针拾遗 (原创)智能指 ...

  5. C++11 智能指针时要避开的 10 大错误

    我很喜欢C++11全新的智能指针,对于那些苦恼于自己管理内存的开发者来说,这是天大的好事.但是,在广泛使用C++11智能指针的两年里,因为使用方法不当而导致程序的效率下降甚至直接crash掉的事情发生 ...

  6. 使用 C++11 智能指针时要避开的 10 大错误

    http://blog.jobbole.com/104666/ 我很喜欢新的C++11的智能指针.在很多时候,对很多讨厌自己管理内存的人来说是天赐的礼物.在我看来,C++11的智能指针能使得C++新手 ...

  7. 十大愚蠢的错误,以避免与C ++ 11智能指针

    Top 10 dumb mistakes to avoid with C++ 11 smart pointers I love the new C++ 11 smart pointers. In ma ...

  8. c++11 智能指针 unique_ptr、shared_ptr与weak_ptr

    C++11中有unique_ptr.shared_ptr与weak_ptr等智能指针(smart pointer),定义在<memory>中. 可以对动态资源进行管理,保证任何情况下,已构 ...

  9. 窥见C++11智能指针

    导语: C++指针的内存管理相信是大部分C++入门程序员的梦魇,受到Boost的启发,C++11标准推出了智能指针,让我们从指针的内存管理中释放出来,几乎消灭所有new和delete.既然智能指针如此 ...

  10. 【C++11新特性】 C++11智能指针之shared_ptr

    http://blog.csdn.net/Xiejingfa/article/details/50750037 原创作品,转载请标明:http://blog.csdn.net/Xiejingfa/ar ...

最新文章

  1. All in one: pentest under metasploit
  2. Java 中的 BigDecimal 类你了解多少?
  3. 互联网1分钟 |1109
  4. Linux ln指令
  5. leetcode面试题 16.19. 水域大小(深度优先搜索)
  6. 为什么80%的码农都做不了架构师?
  7. matplotlib绘制极坐标图像
  8. 20162303 实验五 网络编程与安全
  9. 极简代码(二)—— 转置 list of lists
  10. load data file使用详解
  11. VFP开眼看世界的第一眼,就是学会真正的BS开发,走错一步费三年
  12. c51流水灯实验报告汇编语言,51单片机流水灯实验报告.doc
  13. HDU 4289 Control (最大流最小割)
  14. 信号与系统28(状态变量与状态方程)
  15. python实现函数的最佳平方逼近
  16. sqlite设密工具如何使用(本人资源)
  17. java输出美国的时间_java显示当前美国洛杉矶时间
  18. Linux内存管理之UMA模型和NUMA模型
  19. 多模态 跨模态|人机交互新突破!
  20. python连乘函数_(Python3) 连加 连乘 代码

热门文章

  1. C++11 static_assert
  2. 【李宏毅2020 ML/DL】P53-55 Conditional Generation by RNN Attention Pointer Network Recursive
  3. 修改telnet提示并非_iPhone修改微信提示音,iOS12可用,无需越狱详细教程
  4. 0e php若类型,0e开头MD5 python生成脚本 PHP哈希弱类型比较缺陷
  5. 在 Linux 的应用中测试中的延时和丢包模拟
  6. linux vim 粘贴 没有保持原来的格式,linux中的剪贴板用法,实现vim中原格式粘贴...
  7. [黑金原创教程][连载][iBoard 电子学堂][第〇卷 电子基础]第一篇 认识电子元器件...
  8. 基于JSP的数据库增删改查实现
  9. 使用GDAL构造OpenCV的图像格式
  10. ArcGIS——图形转要素(标注转注记后发布服务问题)