设为首页 加入收藏

TOP

C++11智能指针原理和实现(一)
2019-07-02 16:11:10 】 浏览:139
Tags:智能 指针 原理 实现

一、智能指针起因

  在C++中,动态内存的管理是由程序员自己申请和释放的,用一对运算符完成:new和delete。

  new:在动态内存中为对象分配一块空间并返回一个指向该对象的指针;

  delete:指向一个动态独享的指针,销毁对象,并释放与之关联的内存。

  使用堆内存是非常频繁的操作,容易造成堆内存泄露、二次释放等问题,为了更加容易和更加安全的使用动态内存,C++11中引入了智能指针的概念,方便管理堆内存,使得自动、异常安全的对象生存期管理可行。智能指针主要思想是RAII思想,“使用对象管理资源”,在类的构造函数中获取资源,在类的析构函数中释放资源。智能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象。

  RAII是Resource Acquisition Is Initialization的简称,即资源获取就是初始化:

  1.定义一个类来封装资源的分配与释放;

  2.构造函数中完成资源的分配及初始化;

  3.析构函数中完成资源的清理,可以保证资源的正确初始化和释放;

  4.如果对象是用声明的方式在栈上创建局部对象,那么RAII机制就会正常工作,当离开作用域对象会自动销毁而调用析构函数释放资源。

二、智能指针类型

  智能指针在C++11版本之后提供,包含在头文件<memory>中,标准命名std空间下,有auto_ptr、shared_ptr、weak_ptr、unique_ptr四种,其中auto_ptr已被弃用。

  auto_ptr:拥有严格对象所有权语义的智能指针;

  shared_ptr:拥有共享对象所有权语义的智能指针;

  weak_ptr:到 shared_ptr 所管理对象的弱引用;

  unique_ptr:拥有独有对象所有权语义的智能指针。

2.1 auto_ptr

  auto_ptr是通过由 new 表达式获得的对象,并在auto_ptr自身被销毁时删除该对象的智能指针,它可用于为动态分配的对象提供异常安全、传递动态分配对象的所有权给函数和从函数返回动态分配的对象,是一个轻量级的智能指针,适合用来管理生命周期比较短或者不会被远距离传递的动态对象,最好是局限于某个函数内部或者是某个类的内部。

  声明:

  templateclass T class auto_ptr;

  template<> class auto_ptr<void>;  // 对类型void特化  

  成员函数:

  (1) get: 获得内部对象的指针;

  (2) release:释放被管理对象的所有权,将内部指针置为空,返回内部对象的指针,此指针需要手动释放;

  (3) reset:销毁内部对象并接受新的对象的所有权;

  (4) operator=:从另一auto_ptr转移所有权;

  (5) operator*operator->:访问被管理对象。

  注意事项:

  (1) 其构造函数被声明为explicit,因此不能使用赋值运算符对其赋值,即不能使用类似这样的形式 auto_ptr<int> p = new int;

  (2) auto_ptr 的对象所有权是独占性的,使用拷贝构造和赋值操作符时,会造成对象所有权的转移,被拷贝对象在拷贝过程中被修改;

  (3) 基于第二条,因此不能将auto_ptr放入到标准容器中或作为容器的成员;

  (4) auto_ptr不能指向数组,释放时无法确定是数组指针还是普通指针;

  (5) 不能把一个原生指针交给两个智能指针对象管理,对其它智能指针也是如此。

  auto_ptr是最早期的智能指针,C++11 中已被弃用,C++17 中移除,建议使用unique_ptr代替auto_ptr。

  简单实现:

 1 template<class T>
 2 class AutoPointer
 3 {
 4 public:
 5     AutoPointer(T* ptr)
 6       :mPointer(ptr){}
 7 
 8     AutoPointer(AutoPointer<T>& other)
 9     {
10         mPointer= other.mPointer;  //管理权进行转移
11         other.mPointer= NULL;
12     }
13 
14     AutoPointer& operator = (AutoPointer<T>& other)
15     {
16         if(this != &other)
17         {
18             delete mPointer;
19             mPointer = other.mPointer;  //管理权进行转移
20             other.mPointer= NULL;
21         }
22 
23         return *this;
24     }
25 
26     ~AutoPointer()
27     {
28         delete mPointer;
29     }
30 
31     T& operator * ()
32     {
33         return *mPointer;
34     }
35 
36     T* operator -> ()
37     {
38         return mPointer;
39     }
40 
41 private:
42 
43     T* mPointer;
44 };

2.2 shared_ptr

  shared_ptr多个指针指向相同的对象,也叫共享指针。shared_ptr采用了引用计数的方式,更好地解决了赋值与拷贝的问题,每一个shared_ptr的拷贝都指向相同的内存,每拷贝一次内部的引用计数加1,每析构一次内部的引用计数减1,为0时自动删除所指向的堆内存。shared_ptr内部的引用计数是线程安全的,但是对象的读取时需要加锁。

声明:

  templateclass T class shared_ptr; 

  成员函数:

  (1) get: 获得内部对象的指针;

  (2) swap:交换所管理的对象;

  (3) reset:替换所管理的对象;

  (4) use_count:返回shared_ptr所指对象的引用计数;

  (5) operator*operator->:解引用存储的对象指针;

  (6) operator=:对shared_ptr赋值;

  (7) operator bool:检查是否有关联的管理对象;

  (8) owner_before:提供基于拥有者的共享指针排序。

  交换: std::swap(std::shared_ptr) 特化的swap算法用于交换两个智能指针。

  初始化:通过构造函数传入指针初始化,也可以使用std::make_shared 或 std::allocate_shared 函数初始化。

  注意事项:

  (1) 不能将指针直接赋值给一个智能指针,一个是类,一个是指针。不能使用类似这样的形式 shared_ptr<int> p = new int;

  (2) 避免循环引用,这是shared_ptr的一个最大陷阱,导致内存泄漏,这一点在w

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇求二叉树的高度(非递归) 下一篇正确理解Widget::Widget(QWidget ..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目