智能指针其实也不是完全的指针,应该说是像指针一样的类对象,智能指针通常有指针的功能,当然同时也包含了一些额外的功能。目前比较常见的智能指针有auto_ptr、unique_ptr和shared_ptr三种(其实还有weak_ptr第四种),本篇主要也是讲这三种。

auto_ptr是C++98提出来的,到了C++11基本已经摒弃这种用法,但是一些编译器还没有支持C++11的标准,还用C++98的标准,故而auto_ptr可能还在使用。之所以要用到智能指针是因为在一些情况下,开发者可能声明了一个指针并开辟了内存,但是却忘了释放内存,或者有些情况不是忘了释放内存,而是软件出现异常,释放内存的语句没有被执行到,这些原因都容易造成内存泄漏,这也是智能指针出现的一个原因吧。

1、智能指针的使用

C++的智能指针包含在头文件<memory>中,该头文件中定义了智能指针的函数模板,并且在命名空间std中。在声明一个智能指针的时候要声明数据类型,同时传入开辟的堆内存,这里要强调堆内存,不能是栈内存:

auto_ptr<double> apd(new double);    // OK
unique_ptr<double> upd(new double);  // OK
shared_ptr<double> spd(new double);  // OK
    
int dNUM = 1;
auto_ptr<double> apd(dNUM);          // Error

声明了智能指针后就不需要使用delete语句来释放内存了。

所有的智能指针都有一个explicit构造函数,该函数将指针作为参数,因此不需要自动将指针转换为智能指针对象:

shared_ptr<double> spd;
double *pD = new double;
spd = pD;                        //Error
spd = shared_ptr<double>(pD);    //OK
shared_ptr<double> spd1 = pD;    //Error
shared_ptr<double> spd1(pD);     //OK

智能指针的很多用法都跟普通指针一样,可以对它进行接触引用操作(*)、用->或者.访问成员,还可以将智能指针对象赋值给另一个同类型的对象,但是由于智能指针对象有自动回收内存功能,所以这样做容易导致同一块内存被释放两次的问题。

2、有关智能指针的三个方式

为了避免同块内存被释放两次的惨剧,可以有以下三种方式:

1、定义对象赋值运算符,使之执行深拷贝,这样两个智能指针指向不同的内存;

2、建立所有权(ownership)概念,对于特定对象,只能有一个指针拥有它,也只有拥有它的指针可以删除它,然后,让赋值操作转让所有权,这种方法是auto_ptr和unique_ptr使用的策略,unique_ptr会比auto_ptr严格;

3、使用引用计数(reference counting)创建更智能的指针,跟踪引用特定对象的智能指针的数量,赋值时计数加一,指针过期时计数减一,仅当计数为0的时候才调用delete语句释放内存,这就是shared_ptr使用的策略。

3、为何unique_ptr优于auto_ptr

1、unique_ptr赋值给同类型的unique_ptr操作的时候,编译会报错,而auto_ptr会等到运行时才报错;将unique_ptr赋值给另一个的时候,如果该unique_ptr是个临时的右值,也就是赋值后该unique_ptr不会被使用到,如在函数中返回unique_ptr,那么编译器是一般会通过的

2、unique_ptr使用new和delete、new[]和delete[]两种配套,但是auto_ptr只使用new和delete,所以unique_ptr可以用于数组的变体,但是auto_ptr不能。

4、选择

1、如果程序中会用到多个智能指针指向同一对象,那么肯定要用shared_ptr,包括:有一个指针数组,并使用了一些辅助指针来标识特定元素,如最大最小值等;两个第项都包含第三个对象的指针;STL容器包含指针;

2、不会用多个指针指向同一对象,则用unique_ptr,可将unique_ptr转换为shared_ptr;

3、不支持新标准(如C++11以上的)的编译器,只能用auto_ptr;

溪水急著要流向海洋

浪潮却渴望重回土地

在绿树白花的篱前

曾那样轻易地挥手道别

而沧桑了二十年後

我们的魂魄却夜夜归来

微风拂过时

便化作满园的郁香

C++基础--智能指针的更多相关文章

  1. C++ 基础知识回顾(string基础、智能指针、迭代器、容器类)

    [1] string基础 [1.1] string 的构造 #include <iostream> #include <string> int main() { using n ...

  2. [易学易懂系列|rustlang语言|零基础|快速入门|(21)|智能指针]

    [易学易懂系列|rustlang语言|零基础|快速入门|(21)|智能指针] 实用知识 智能指针 我们今天来讲讲Rust中的智能指针. 什么是指针? 在Rust,指针(普通指针),就是保存内存地址的值 ...

  3. c++基础 使用智能指针

    三个智能指针模板(auto_ptr.unique_ptr和shard_ptr)都定义了类似指针的对象(c++11已将auto_ptr摒弃),可以将new获得(直接或间接) 的地址赋给这种对象.当智能指 ...

  4. Boost智能指针-基础知识

    简单介绍 内存管理一直是 C++ 一个比較繁琐的问题,而智能指针却能够非常好的解决问题,在初始化时就已经预定了删除.排解了后顾之忧.1998年修订的第一版C++标准仅仅提供了一种智能指针:std::a ...

  5. ndk学习之c++语言基础复习----C++线程与智能指针

    线程 线程,有时被称为轻量进程,是程序执行的最小单元. C++11线程: 我们知道平常谈C++线程相关的东东基本都是基于之后要学习的posix相关的,其实在C++11有自己新式创建线程的方法,所以先来 ...

  6. C++ 中的智能指针-基础

    简介 在现代 C++ 编程中,标准库包含了智能指针(Smart pointers). 智能指针用来确保程序不会出现内存和资源的泄漏,并且是"异常安全"(exception-safe ...

  7. 【UE4 C++ 基础知识】<15> 智能指针 TSharedPtr、UniquePtr、TWeakPtr、TSharedRef

    基本概念 UE4 对 UObject 对象提供垃圾回收 UE4 对原生对象不提供垃圾回收,需要手动进行清理 方式 malloc / free new / delete new与malloc的区别在于, ...

  8. C++智能指针

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

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

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

随机推荐

  1. 物流跟踪 调用快递鸟API

    概要:关于调用快递鸟API,我有几句话想说,有几行代码想写 业务需求:就是做做商城,卖卖东西.然后需要做个物流跟踪的功能 需要获取的信息大概就是这个样子 现在看这个快递怎么这么慢 如何实现? 直接调用 ...

  2. Jackson自定义反序列化

    // 设置jackson时间反系列化格式 SimpleModule module = new SimpleModule(); module.addDeserializer(Date.class, ne ...

  3. Django(十五)模板详解:模板标签、过滤器、模板注释、模板继承、html转义

    一.模板的基础配置及使用 [参考]https://docs.djangoproject.com/zh-hans/3.0/topics/templates/ 作为Web框架,Django提供了模板,用于 ...

  4. 吴裕雄--天生自然JAVA数据库编程:处理大数据对象

    import java.sql.Connection ; import java.sql.DriverManager ; import java.sql.SQLException ; import j ...

  5. arm linux 移植 ffmpeg 库 + x264

    背景 Ffmpeg 中带有h264的解码,没有编码,需要添加x264.libx264是一个自由的H.264编码库,是x264项目的一部分,使用广泛,ffmpeg的H.264实现就是用的libx264. ...

  6. 关于netty配置的理解serverBootstrap.option和serverBootstrap.childOption

    The parameters that we set using ServerBootStrap.option apply to the ChannelConfig of a newly create ...

  7. spingboot2.0外部引入xml配置文件时找不到文件等报错

    之前的项目可以启动,后面不知道为什么都不行了,报错如下: SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found bindin ...

  8. synchronized和锁(ReentrantLock) 区别

    synchronized和锁(ReentrantLock) 区别 java的两种同步方式, Synchronized与ReentrantLock的区别 并发(一):理解可重入锁 可重入锁和不可重入锁 ...

  9. 使用JS写一个计算器

    先上效果图: 简单的加减乘除功能还是有的,所以我们就考虑怎么来实现这个功能. 根据预期效果,可以确定页面中的布局要用到table tr td. 所以先放上页面布局,table的边框宽度border,c ...

  10. jsp获取web的跟路径

    我实现了一个listener,此listener在tomcat启动的时候读取项目的配置文件,配置文件是xml.但是读取解析的功能是在另一个工具类实现的. 这个普通的工具类B,如何获取到当前web的跟路 ...