一、简介

  参考这篇博客,并且根据《C++ Primer》中相关知识,我总结了C++关于智能指针方面的内容。

  为了解决内存泄漏的问题,便出现了智能指针。STL提供的智能指针有:auto_ptr,unique_ptr,shared_ptr和weak_ptr。其中auto_ptr是C++98提供的方案,C++11已经将其摒弃,并提供了unique_ptr和shared_ptr。

  所有的智能指针都有一个explicit构造函数,以指针作为参数,比如auto_ptr的类模板原型为:

templet<class T>
class auto_ptr {
explicit auto_ptr(T* p = 0) ;
...
};

  因此不能够自动将指针转换为智能指针,并且显示构造:

shared_ptr<double> pd;
double *p_reg = new double;
pd = p_reg; // not allowed (implicit conversion)
pd = shared_ptr<double>(p_reg); // allowed (explicit conversion)
shared_ptr<double> pshared = p_reg; // not allowed (implicit conversion)
shared_ptr<double> pshared(p_reg); // allowed (explicit conversion)

  且所有的指针都应该避免以下情况:

string vacation("I wandered lonely as a cloud.");

//pvac过期时,程序将把delete运算符用于非堆内存,这是错误的。
shared_ptr<string> pvac(&vacation); // No

二、auto_ptr

  • 基本用法
//用法一:构造
std::auto_ptr<MyClass> m_example(new MyClass()); //用法二:重置auto\_ptr并且拥有另一个对象
std::auto_ptr<MyClass> m_example(new MyClass());
m_example.reset(new MyClass()); //用法三:指针的赋值操作
std::auto_ptr<MyClass> m_example1(new MyClass());
std::auto_ptr<MyClass> m_example2(new MyClass());
m_example2 = m_example1; //用法四:撤销主动权,返回其控制的指针
std::auto_ptr<MyClass> m_example1(new MyClass());
MyClass* pt = m_example1.release(); //用法五:返回保存的指针,和四不同,此时auto_ptr还控制着该指针
std::auto_ptr<MyClass> m_example1(new MyClass());
MyClass* pt = m_example1.get();
  • 注意,在用法三的赋值操作中,C++会把m_example1所指向的内存回收,使m_example1 的值为NULL,所以在C++中,应绝对避免把auto_ptr放到容器中。即应避免下列代码:
/*
当用算法对容器操作的时候,你很难避免STL内部对容器中的元素实现赋值传递,这样便会使容器中多个元素被置位NULL,而这不是我们想看到的。
*/
vector<auto_ptr<MyClass>>m_example;

三、shared_ptr

  • 基本用法
shared_ptr<T> sp //空智能指针,可以指向类型为T的对象
sp.get() //返回sp中保存的指针
swap(p,q)
p.swap(q) //交换p和q中的指针
make_shared<T>(args) //返回一个智能指针,指向动态分配的类型为T的对象
shared_ptr<T>p(q) //递增q中指针的计数器
p = q //递增q中指针的计数器,递减原来p中指针的计数器
p.user_count() //返回与p共享对象的智能指针的数量(包括自己)
p.unique() //若p.user_count()为1,返回true
  • 注意

    • 当指向一个对象的最后一个shared_ptr被销毁时,shared_ptr类会自动销毁此对象;
    • 函数中return智能指针将让计数加一;
    • 尽量不要通过get()函数得到的原指针给别的shared_ptr构造,如下:
    shared_ptr<int> p(new int(42));
    int *q = p.get();
    { //新程序块
    shared_ptr<int> tmp(q);
    } //被销毁,且其内存也会被销毁
    int foo = *p; //未定义,空悬指针
  • 自定义释放操作

void end_connection(connection *p) { disconnect(*p); }

void f(destination &d) {
connection c = connection(&d);
shared_ptr<connection> p(&c, end_connection);
//当f退出时,自动调用end_connection断开连接
}

四、unique_ptr

  与shared_ptr不同,某个时刻只能有一个unique_ptr指向一个给定对象。当unique_ptr被销毁时,其对象也被销毁。

  • 基本用法
unique_ptr<T> up //空智能指针,可以指向类型为T的对象
unique_ptr<T,D> up //使用类型为D的可调用对象来释放它的指针
up.get() //返回sp中保存的指针
swap(p,q)
p.swap(q) //交换p和q中的指针
u = nullptr //释放u指向的对象,将u置空
u.release() //返回原指针,放弃控制器,将u置空
u.reset() //释放u指向的对象
u.reset(q) //令u指向q这个对象,原对象被释放
  • 自定义释放操作
void end_connection(connection *p) { disconnect(*p); }

void f(destination &d) {
connection c = connection(&d);
unique_ptr<connection,decltype(end_connection)> p(&c, end_connection);
//当f退出时,自动调用end_connection断开连接
}

五、weak_ptr

  weak_ptr是一种不控制所指对象生存期的只能指针,它指向由一个shared_ptr管理的对象。将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个shared_ptr销毁,无论是否有weak_ptr,对象都会被销毁。

  • 基本用法
weak_ptr<T> w //空智能指针,可以指向类型为T的对象
weak_ptr<T> w(sp) //绑定一个shared_ptr
w = p //p可以是shared_ptr或weak_ptr
w.reset() //将w置空
w.use_count() //与w共享的shared_ptr数量
w.expired() //若use_count()为0,返回true
w.lock() //若expired为true,返回一个shared_ptr,否则返回一个指向w的对象的shared_ptr

论C++的智能指针的更多相关文章

  1. enote笔记法使用范例(2)——指针(1)智能指针

    要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...

  2. C++11 shared_ptr 智能指针 的使用,避免内存泄露

    多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...

  3. C++智能指针

    引用计数技术及智能指针的简单实现 基础对象类 class Point { public: Point(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) { ...

  4. EC笔记:第三部分:17、使用独立的语句将newed对象放入智能指针

    一般的智能指针都是通过一个普通指针来初始化,所以很容易写出以下的代码: #include <iostream> using namespace std; int func1(){ //返回 ...

  5. 智能指针shared_ptr的用法

    为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer). 智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈 ...

  6. 智能指针unique_ptr的用法

    unique_ptr是独占型的智能指针,它不允许其他的智能指针共享其内部的指针,不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr,如下面错误用法: std::unique_pt ...

  7. 基于C/S架构的3D对战网络游戏C++框架 _05搭建系统开发环境与Boost智能指针、内存池初步了解

    本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...

  8. C++ 引用计数技术及智能指针的简单实现

    一直以来都对智能指针一知半解,看C++Primer中也讲的不够清晰明白(大概是我功力不够吧).最近花了点时间认真看了智能指针,特地来写这篇文章. 1.智能指针是什么 简单来说,智能指针是一个类,它对普 ...

  9. C++11智能指针读书笔记;

    智能指针是一个类对象,而非一个指针对象. 原始指针:通过new建立的*指针 智能指针:通过智能指针关键字(unique_ptr, shared_ptr ,weak_ptr)建立的指针 它的一种通用实现 ...

  10. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

随机推荐

  1. Asp.Net Core轻松入门之WebHost的配置

    在本篇文章中,我来讲一讲如何利用WebHost来加载配置文件和设置启动的Url 在前面的文章中讲过,ASP.Net Core应用程序会自动加载appsettings.json中的配置文件,那么如果配置 ...

  2. haproxy反向代理配置示例

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  3. luogu【P2745】[USACO5.3]窗体面积Window Area

    这个题 就是个工程题 (然而一开始我并不知道怎么做..还是看nocow的..qwq)(原题入口) 算法为 离散化 + 扫描线  将大坐标变小  并且 用横纵坐标进行扫描 来计算面积 一开始 我想边添加 ...

  4. [SCOI2007]降雨量

    ST表,再大力讨论一下(因为lower_bound和upper_bound,WA了一次) # include <bits/stdc++.h> # define RG register # ...

  5. HTTP请求过程-域名解析和TCP三次握手建立链接

    我们在浏览器输入http://www.baidu.com想要进入百度首页,但是这是个域名,没法准确定位到服务器的位置,所以需要通过域名解析,把域名解析成对应的ip地址,然后通过ip地址查找目的主机.整 ...

  6. hadoop-eclipse-plugin-2.x.x 插件编译

    在网上找的hadoop for eclipse 插件都不能用,决定自己去编译一个.Hadoop 提供了一个 Eclipse 插件以方便用户在 Eclipse 集成开发环境中使用 Hadoop,如管理 ...

  7. 大数据(1):基于sogou.500w.utf8数据的MapReduce程序设计

    环境:centos7+hadoop2.5.2 1.使用ECLIPS具打包运行WORDCOUNT实例,统计莎士比亚文集各单词计数(文件SHAKESPEARE.TXT). ①WorldCount.java ...

  8. 纯代码实现WordPress评论回复自动添加@评论者的功能

    先看看效果: 这个有什么用呢?添加了@功能之后那些用户评论之间的层次关系就很清晰了,我们可以清楚地知道这些评论是谁发给谁的. 其实主要是为了提升逼格. 实现方法: 将下面代码加入function.ph ...

  9. 【Unity与23种设计模式】抽象工厂模式(Abstract Factory)

    GoF中定义: "提供一个能够建立整个类群组或有关联的对象,而不必指明它们的具体类." 意思就是 根据不同的执行环境产生不同的抽象类子类 抽象工厂模式经常在面试中会涉及到 下面的例 ...

  10. Spring源码学习:第2步--使用SLF4j+Log4j日志框架替换掉其自身的commons-logging日志框架

    正如Spring官方文档所述,其底层的实现选择了commons-logging作为日志框架.这一"失足"性的选择,竟连Spring自身都抱怨.但是,谁叫Spring如此优秀呢,即使 ...