本文参考C++智能指针简单剖析

内存泄露

我们知道一个对象(变量)的生命周期结束的时候, 会自动释放掉其占用的内存(例如局部变量在包含它的第一个括号结束的时候自动释放掉内存)

int main () {
{
int a = 1;
printf("%d\n", a);
}
{
a = 2;
printf("%d\n", a);
}
}

这样会编译错误.

但是如果这样写呢?

void func(int &o) {
int *p = new int(o);
return;
}

程序结束的时候会自动释放p的内存, 但是由new算符创建的匿名变量却一直留在内存中, 这就为内存泄露留下了隐患.

所以在程序结尾要加上delete p, 释放掉p指向的变量占用的内存.

那么能不能在指针过期的时候自动释放掉它指向的内存呢?

可惜它不是具有析构函数的类对象指针.

如果这个指针本身就是个对象, 它就可以实现在指针本身离开作用域的时候释放其指向的内存的析构函数了.

这就是auto_ptr, shared_ptr, unique_ptr几个智能指针背后的设计思想.可以理解为这个指针本身就是一个对象, 因为它具有对象的行为.

可以将上述有问题的代码改写为这样:

void func(int &o) {
auto_ptr<int> p(new int(o));
}

这样在函数结束的时候内存就会被释放了.

智能指针

这个东西是在C++98提供的.C++11已经抛弃了它并且提供了另外两种解决方案.

如果没有C++11的话就只能使用这个东西了.

不允许隐形转换

所有的智能指针都有一个explicit构造函数, 以指针为参数.

这个东西大概可以这样写

template <class T>
class auto_ptrs {
private:
T* ptr;
public:
explicit auto_ptrs (T* p = 0): ptr(p) {}
~auto_ptrs() { delete ptr; printf("delete\n"); }
};
int main () {
{
auto_ptrs<int> p (new int(1));
auto_ptr<int> ptr, pt(new int(2));
ptr = auto_ptr<int>(new int(3));
}
}

只能用于堆内存

int main() {
int a = 0;
std:: auto_ptr<int> p(&a);
}

这样写是错误的, 因为它会在main&a执行delete操作, 而a位于栈内存, 不能被delete.

unique_ptr代替auto_ptr

如果将一个指针赋值给另一个指针呢?

class Int{
int a;
public:
int J() {return a;}
Int(int _) : a(_) {}
~Int() { printf("delete\n"); }
};
int main() {
auto_ptr<Int> p (new Int(123456789));
auto_ptr<Int> q;
q = p;
}

如果在p, q作用域结束的时候分别delete一次, 那么就会delete同一个变量两次, 这样是不行的.

有很多种解决方案可以解决这个问题:

  • 深度复制, 就是将指针指向的内存复制一遍再让另一个指针指向它.
  • 转让所有权, 由于一个对象只能由一个对象所拥有, 另一个就变空指针了, 只让拥有对象的指针删除该对象.(auto_ptrunique_ptr的策略)
  • 跟踪引用特定对象的智能指针数.——引用计数(shared_ptr的策略), 如果一个对象被引用了p次, 那么得当指针全部销毁时对象才会销毁.

但是用auto_ptr还是有一个问题, 如果q = p之后又调用了*p, 对一个空指针解除引用程序是会崩溃的.

unique_ptr的好处是如果你这样写

unique_ptr<Int> p (new Int(1));
unique_ptr<Int> q;
q = p;

你会得到一个编译错误, 原因是避免潜在的内存崩溃问题.

但是如果你把一个临时的unique_ptr赋值给unique_ptr却不会出现问题, 这是它聪明的地方.

例如

unique_ptr<int> func(int &a) {
unique_ptr<int> p(&a);
return p;
}

或者

unique_ptr<int> a;
a = unique_ptr<int> (new int(199));

你甚至可以将unique_ptr显性转化为shared_ptr, 当然对象也被接管.

C++智能指针: auto_ptr, shared_ptr, unique_ptr, weak_ptr的更多相关文章

  1. C++11 新特性之智能指针(shared_ptr, unique_ptr, weak_ptr)

    这是C++11新特性介绍的第五部分,涉及到智能指针的相关内容(shared_ptr, unique_ptr, weak_ptr). shared_ptr shared_ptr 基本用法 shared_ ...

  2. C++ | 再探智能指针(shared_ptr 与 weak_ptr)

    上篇博客我们模拟实现了 auto_ptr 智能指针,可我们说 auto_ptr 是一种有缺陷的智能指针,并且在C++11中就已经被摈弃掉了.那么本章我们就来探索 boost库和C++11中的智能指针以 ...

  3. 智能指针auto_ptr & shared_ptr

    转载:智能指针auto_ptr 很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生 ...

  4. C++11智能指针之std::unique_ptr

    C++11智能指针之std::unique_ptr   uniqut_ptr是一种对资源具有排他性拥有权的智能指针,即一个对象资源只能同时被一个unique_ptr指向. 一.初始化方式 通过new云 ...

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

    C++中的智能指针首先出现在“准”标准库boost中.随着使用的人越来越多,为了让开发人员更方便.更安全的使用动态内存,C++11也引入了智能指针来管理动态对象.在新标准中,主要提供了shared_p ...

  6. C++智能指针之shared_ptr与右值引用(详细)

    1. 介绍 在 C++ 中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露.解决这个问题最有效的方法是使用智能指针(smart pointer).智能指针是存储指向动态分配(堆)对象指针 ...

  7. 关于智能指针auto_ptr

    智能指针auto_ptr和shared_ptr也是面试中经常被问到的一个 感觉看auto_ptr的源码反而更加容易理解一些,因为源码的代码量并不大,而且比较容易理解. 本篇主要介绍auto_ptr 其 ...

  8. 【C++智能指针 auto_ptr】

    <More Effective C++>ITEM M9他提到auto_ptr.说是当异常产生的时候.怎么释放为对象分配的堆内存,避免反复编写内存释放语句. PS:这里书里面提到函数退出问题 ...

  9. 智能指针之shared_ptr基本概述

    1.shared_ptr允许有多个指针指向同一个对象,unique_ptr独占所指向的对象. 2.类似于vector,智能指针也是模板.创建智能指针: shared_ptr<string> ...

随机推荐

  1. Android 内核--Context对象

    Context(在Android中翻译为场景):一个Activity就是一个Context,一个Service也是一个Context,应用程序中有多少个Activity或者Service,就会有多少个 ...

  2. CF993E Nikita and Order Statistics

    小于x的赋值为1,否则为0 区间等于k的个数 求0~n连续的n+1个k? N<=1e5? FFT! 考虑卷积建模:用下标相加实现转移到位,数值相乘类比乘法原理! 法一: 分治,然后FFT没了 法 ...

  3. JS 中类型鉴别

    JS中的基本类型有:数字(Number(NaN,Infinity)),字符串(String),Undefined,Null,Boolean 引用类型有:数组(Array),对象(Object),函数( ...

  4. C语言实现单链表的遍历,逆序,插入,删除

    单链表的遍历,逆序,插入,删除 #include<stdio.h> #include<stdlib.h> #include <string.h> #define b ...

  5. java RSA加密解密实现(含分段加密)

    该工具类中用到了BASE64,需要借助第三方类库:javabase64-1.3.1.jar 下载地址:http://download.csdn.net/detail/centralperk/50255 ...

  6. [洛谷P3460] [POI2007]TET-Tetris Attack

    洛谷题目链接:[POI2007]TET-Tetris Attack 题目描述 A puzzle called "Tetris Attack" has lately become a ...

  7. Scala环境安装设置

    Scala语言可以安装在任何类UNIX或Windows系统.要安装Scala,必须先安装Java1.5或更高版本安装在计算机上. Windows上安装Scala: 步骤(1):JAVA设置: 首先,必 ...

  8. 社会网络分析——Social Network Analysis

    什么是社会网络分析,英文social network analysis.现在这个分析越来越时髦,也越来越显现其在社会科学的研究价值.我在2000年的时候受祝建华老师的邀请到香港城市大学作研究,接触到 ...

  9. 【Nginx】不改系统源代码的情况下,动态网站离线缓存方案

    背景: 公司的一套系统,由前端.界面.服务层.大数据开发平架等多层组成,每一层被划分为多个模块,每个模块会依赖若干组建.由于公司的这套系统是部署在内网环境中的,现在需要拿出去给客户演示,用一个笔记本装 ...

  10. XAMPP 启动mysql报错 InnoDB: Error: could not open single-table tablespace file……

    昨天安装了最新版本XAMPP for Windows 1.8.3. 今天早上打开XAMPP双击mysql Start按钮报错,如下(部分截取): 2013-09-17 10:12:02 9012 [E ...