C++ primer plus 16.2节介绍了auto_ptr,该模板类在C++11中已弃用,目前已被shared_ptr代替。

auto_ptr又叫做智能指针,用于管理动态内存分配的用法。

为什么要有auto_ptr?

首先看一个例子,

void remodel(string &str){
string *ps = new string(str);
...
str = ps;
return;
}

此例子有什么缺陷呢?

函数结束的时候没有释放内存,这导致了内存的泄露,指针ps会被释放,但是其指向的内存并没有被释放。一般来说,解决new导致的内存泄露的方法是在return之前使用delete.

但凡是涉及到“别忘了”的操作,都不是最佳的操作,因为一定会有开发者忘记,或者在不经意间删除或者注释掉了这些代码。

就算是没有忘记,也会因为一些别的操作导致内存无法释放,例如以下的代码:

void remodel(string &str)
{
string *ps = new string(str);
...
if(xxx){
throw exception();
}
str = *ps;
delete ps;
return;
}

在delete执行之前,如果执行过程中产生了异常并抛出,则后续的指令都不会执行,这仍将导致内存泄露。

如何解决

首先,我们知道,C++创建一个对象有两种方式,new和直接声明。new一个对象将在堆中动态分配内存来创建一个对象,而直接声明将会在栈内存中创建对象。

(所谓的堆,是指程序内部除了栈和静态存储区之外的"自由空间(free store)",堆内存用于在程序运行时分配对象。)

前者的生命周期是全局的,后者则受到作用域限制,也就是说对于前者产生的对象,如果不去主动释放它,则该对象所占据的内存会一直存在,如果没有指针可以指向它,则会导致内存泄露。

而直接声明的对象,在一个类对象过期的时候,析构函数会在一个对象过期的时候自动执行从而将该对象释放。

不妨这样思考,如果指针能被封装为一个对象,则这个包含指针的对象过期的时候调用其析构函数,将该指针指向的对象delete,不就能够把它指向的内存也释放了吗?

于是auto_ptr便诞生了,auto_ptr是一个模板类,这样便可以创建指向任何类型的智能指针。

auto_ptr的设计和使用

template<class T>class auto_ptr{
public:
explicit auto_ptr(T* p = 0) throw();
};

throw()意味着构造函数不引发异常,因此请求T类型的auto_ptr将获得一个指向T类型的auto_ptr.

这样便定义好了一个智能指针,其实非常简单,就是在构造的时候将普通的指针放入了auto_ptr模板类中

使用的时候

auto_ptr<double> ap(new double);//在构造函数中填入new出来的对象
*ap = 23.3;//ap对象的地址其实就是new出来的double对象的地址,所以可以用指针取值的方式赋值。

所以,改造文章开头的remodel函数:

void remodel(string &str){
auto_ptr<string> ps(new string(str));
...
if(xxx) throw exception(); str=*ps;
return;
}

这里,便不再需要使用delete了。

shared_ptr和unique_ptr

C++11摒弃了auto_ptr,主要是由于auto_ptr无法进行指针的传递。auto_ptr必须显式地初始化,即auto_ptr<string> ps(new string("sdf")),

为了多个指针指向一个new出的对象,C++11提出了shared_ptr,

shared_ptr中增加了引用计数,有N个指向一个同一个内存区域的shared_ptr时,它们共同维护一个引用计数器。

shared_ptr的大概实现如下:

template<typename T> class shared_ptr{

private:
T* _ptr;//指向的对象
int *_count;//引用计数器 public:
...
shared_ptr():_ptr((T*)0),_count(0){}
~shared_ptr(){
if(_ptr && --*count==0){
delete _ptr;
delete _count;
}
}
};

当智能指针的析构函数启用时,只有引用计数为0的时候,才会进行析构。

C++的智能指针学习笔记(初)的更多相关文章

  1. C++中的智能指针、轻量级指针、强弱指针学习笔记

    一.智能指针学习总结 1.一个非const引用无法指向一个临时变量,但是const引用是可以的! 2.C++中的delete和C中的free()类似,delete NULL不会报"doubl ...

  2. Qt 智能指针学习(7种指针)

    Qt 智能指针学习 转载自:http://blog.csdn.net/dbzhang800/article/details/6403285 从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ ...

  3. Android 智能指针学习 一

    Android5.1 中智能指针涉及的文件如下: system/core/include/utils/RefBase.h system/core/libutils/RefBase.cpp system ...

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

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

  5. Qt 智能指针学习(7种QT的特有指针)

    从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...

  6. Qt 智能指针学习(7种QT智能指针和4种std智能指针)

    从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...

  7. Qt 智能指针学习

    原地址:http://blog.csdn.net/dbzhang800/article/details/6403285 从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include & ...

  8. [转]Qt 智能指针学习

    从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...

  9. c++——智能指针学习(shared_ptr和weak_ptr)

    先看一个例子:Stark和Targaryen家族你中有我,我中有你.我们设计以下类企图避免内存泄漏,使得析构函数都能调用到: #include<iostream> #include< ...

随机推荐

  1. BUU-CTF[CISCN2019 华东南赛区]Web11

    BUU-CTF[CISCN2019 华东南赛区]Web11 页面最下端有提示Build with Smarty ! 确定页面使用的是Smarty模板引擎.输入{$smarty.version}就可以看 ...

  2. Python语法之选择和循环(if、while)

    前言:在程序开发中,一共有三种流程方式: 顺序:从上向下,顺序执行代码 分支:根据条件判断,决定执行代码的分支 循环:让特定代码重复执行(解决程序员重复工作) 1.判断的定义: 如果条件满足,才能做某 ...

  3. Python语法之函数、引用和装饰器

    所谓函数,就是把具有独立功能的代码块组织成为一个小模块,在需要的时候调用 函数是带名字的代码块,用于完成具体的工作 需要在程序中多次执行同一项任务时,你无需反复编写完成该任务的代码,而只需调用该 任务 ...

  4. Disable_functions绕过整合

    转载 https://whoamianony.top/2021/03/13/Web安全/Bypass Disable_functions/ https://www.mi1k7ea.com/2019/0 ...

  5. Jetpack Compose学习(3)——图标(Icon) 按钮(Button) 输入框(TextField) 的使用

    原文地址: Jetpack Compose学习(3)--图标(Icon) 按钮(Button) 输入框(TextField) 的使用 | Stars-One的杂货小窝 本篇分别对常用的组件:图标(Ic ...

  6. NOIP模拟14「队长快跑·影魔·抛硬币」

    T1:队长快跑 基本思路:   离散化·DP·数据结构优化DP   这三个我都没想到....气死.   定义状态数组:\(c[i][j]\)表示在i时最小的a值是j时可以摧毁的最多的水晶数.   那么 ...

  7. 使用Redis Stream来做消息队列和在Asp.Net Core中的实现

    写在前面 我一直以来使用redis的时候,很多低烈度需求(并发要求不是很高)需要用到消息队列的时候,在项目本身已经使用了Redis的情况下都想直接用Redis来做消息队列,而不想引入新的服务,kafk ...

  8. (7)java Spring Cloud+Spring boot+mybatis企业快速开发架构之SpringCloud-Spring Boot Starter的介绍及使用

    ​ Spring Boot 的便利性体现在,它简化了很多烦琐的配置,这对于开发人员来说是一个福音,通过引入各种 Spring Boot Starter 包可以快速搭建出一个项目的脚手架推荐分布式架构源 ...

  9. php curl下载文件由于空格导致下载文件失败

    <?php //$result=httpcopy('http://www.phpernote.com/image/logo.gif'); echo '<pre>';print_r($ ...

  10. dede编辑文章不更新时间的方法

    在修改文章的时候,发现织梦DEDECMS5.7这个版本存在一个问题,修改文章的同时也修改了文章的发布时间,这个 功能可能有些人比较需要,但同时也有些站长朋友又不需要,因为我们编辑某个文章的时候,发现编 ...