C++--深度理解智能指针

这篇具有很好参考价值的文章主要介绍了C++--深度理解智能指针。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

PS:智能指针简单应用看这里  http://t.csdn.cn/qN7IK

1.智能指针的介绍

在C++中,智能指针有三个版本,分别为:

auto_ptr  unique_ptr shared_ptr 

这三个版本的智能指针中,shared_ptr最为完善,auto_ptr基本上没有太大用处,unique_ptr的使用场景并不多。对于智能指针来说,需要实现RAII和重载operator*和operator->,使它具有像指针一样的行为。

2.智能指针分析

    2.1 auto_ptr版本

        auto_ptr简单实现:

    template<class T>
	class Auto_ptr
	{
	public:
        //管理权转移 auto_ptr
		Auto_ptr(T* ptr)
			:_ptr(ptr)
		{}

		Auto_ptr(Auto_ptr<T>& ptr)
			:_ptr(ptr._ptr)
		{
			ptr._ptr=nullptr;
		}

		T& operator=(const T& ptr)
		{
			if (this != &ptr)
			{
				if (_ptr)
				{
					cout << "Delete:" << _ptr << endl;
					delete _ptr;
				}

				_ptr = ptr._ptr;
				ptr._ptr = nullptr;
			}

			return *this;

		}
        //析构函数需要写重载,不同常见需要不同析构函数
		/*~Auto_ptr()
		{
			if (_ptr)
			{
				delete _ptr;
			}
		}*/
		T& operator*()
		{
			return *this;
		}

		T* operator->()
		{
			return this;
		}
	private:
		T* _ptr=nullptr;
	};

由于auto_ptr支持拷贝构造,为了确保指针所有者唯一,这里转移了所有权,转移所有权之后,导致了被拷贝的为空了,这是一大缺点,导致auto_ptr被遗弃。

2.2.unique_ptr的使用   

template<class T>
	class Unique_ptr
	{
	public:
		Unique_ptr(T* ptr)
			:_ptr(ptr)
		{}

		Unique_ptr(Auto_ptr<T>& ptr) = delete;
		
		T& operator=(const T& ptr) = delete;
		/*~Auto_ptr()
		{
			if (_ptr)
			{
				delete _ptr;
			}
		}*/
		T& operator*()
		{
			return *this;
		}

		T* operator->()
		{
			return this;
		}
	private:
		T* _ptr = nullptr;
	};

    unique_ptr的底层直接没有使用拷贝构造和赋值重载,导致它只能使用在不需要拷贝构造和复制重载的场景上,所以unique_ptr的缺点为unique_ptr 不共享它的指针。 它无法复制到其它unique_ptr,无法通过值传递到函数,也无法用于需要副本的任何标准模板库 (STL) 算法。 只能移动unique_ptr 。 这意味着,内存资源所有权将转移到另一 unique_ptr,并且原始 unique_ptr 不再拥有此资源。

2.3 shared_ptr的使用

template<class T>
	class Shared_ptr
	{
	public:
		Shared_ptr(T* ptr=nullptr)
			:_ptr(ptr)
			,_Pcount(new int(1))
		{
			;
		}
		void Release()
		{
			if (--(*_Pcount) == 0)
			{
				cout << "Delete:" << _ptr << endl;
				delete _ptr;
				delete _Pcount;
			}
		}

		~Shared_ptr()
		{
			Release();
		}

		Shared_ptr(Smart_ptr<T>& ptr)
			:_ptr(ptr)
		{
			(*_Pcount)++;
			ptr = nullptr;
		}
		Shared_ptr& operator=(Smart_ptr& ptr)
		{
			if (_ptr == ptr._ptr)
				return *this;
			Release();
			--(*_Pcount);

			_ptr = ptr._ptr;
			_Pcount = ptr._Pcount;
			*_Pcount++;
			return *this;
		}
		T& operator*()
		{
			return *_ptr;
		}
		T* operator->()
		{
			return _ptr;
		}
	private:
		T* _ptr;
		int* _Pcount;
	};

在unique_ptr的基础上,新增加了一个版本,为shared_ptr版本。

基本原理:就是记录对象被引用的次数,当引用次数为 0 的时候,也就是最后一个指向该对象的共享指针析构的时候,共享指针的析构函数就把指向的内存区域释放掉。

特点:它所指向的资源具有共享性,即多个shared_ptr可以指向同一份资源,并在内部使用引用计数机制来实现这一点。

共享指针内存:每个 shared_ptr 对象在内部指向两个内存位置:

  • 指向对象的指针;
  • 用于控制引用计数数据的指针。

当新的 shared_ptr 对象与指针关联时,则在其构造函数中,将与此指针关联的引用计数增加1。

当任何 shared_ptr 对象超出作用域时,则在其析构函数中,它将关联指针的引用计数减1。如果引用计数变为0,则表示没有其他 shared_ptr 对象与此内存关联,在这种情况下,它使用delete函数删除该内存。

shared_ptr像普通指针一样使用,可以将*和->与 shared_ptr 对象一起使用,也可以像其他 shared_ptr 对象一样进行比较。

但是,对于shared_ptr来说,依然有一个缺点,如果是循环引用,那么将会出现bug,这时候就需要使用weak_ptr.

2.4 weak_ptr使用

weak_ptr是一个弱引用的智能指针,它可以与shared_ptr一起使用。weak_ptr不会增加所管理的对象的引用计数,因此它不会影响对象的生命周期。可以通过weak_ptrlock()成员函数来获取一个指向所管理的对象的shared_ptr

3.总结:

3.1 智能指针原理:

智能指针解决问题的思想:将常规指针进行包装,当智能指针对象过期时,让它的析构函数对常规指针进行内存释放。

auto_ptr(C++98的方案,C++11已经废弃):采用所有权模式,对于特定的对象,只能有一个智能指针可拥有它,这样只有拥有对象的智能指针的析构函数会删除该对象。然后,让赋值操作转让所有权。

unique_ptr(替代 auto_ptr):也是采用所有权模式,实现独占式拥有或严格拥有概念,保证同一时间内只有一个智能指针可以指向该对象。

shared_ptr:采用引用计数实现共享式拥有概念。多个智能指针可以指向相同对象,该对象和其相关资源会在最后一个引用被销毁时候释放。它使用引用计数来表明资源被几个指针共享。例如,赋值时,计数将加 1,而指针过期时,计数将减 1。仅当最后一个指针过期时,才调用 delete。

weak_ptr:该类型指针通常不单独使用(没有实际用处),只能和 shared_ptr 类型指针搭配使用。weak_ptr 类型指针并不会影响所指堆内存空间的引用计数,可以用来解决循环引用问题。

3.2 使用场景

如果在程序中使用new 从堆(自由存储区)分配内存,等到不再需要时,应使用 delete 将其释放,如果忘记释放,则会产生内存泄露。C++ 引入了智能指针, 以帮助自动完成这个过程。智能指针是行为类似于指针的类对象。如果程序要使用多个指向同一个对象的指针,应该选择shared_ptr;如果程序不需要多个指向同一个对象的指针,则可以使用unique_ptr;如果使用new [] 分配内存,应该选择 unique_ptr;如果函数使用new 分配内存,并返回指向该内存的指针,将其返回类型声明为 unique_ptr 是不错的选择。文章来源地址https://www.toymoban.com/news/detail-686715.html

到了这里,关于C++--深度理解智能指针的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言——深入理解指针(3)

    目录 1. 字符指针 2. 数组指针 2.1 数组指针变量 2.2 数组指针变量的初始化 3.二维数组传参(本质) 4. 函数指针 4.1 函数指针变量的创建 4.2 函数指针的使用 4.3 typedef  5. 函数指针数组 6. 转移表(函数指针数组的使用) 在指针的类型中有一种指针类型为字符指针  char*    举例

    2024年02月05日
    浏览(54)
  • 【C语言:深入理解指针二】

    我们知道,指针变量也是变量,它也有自己的地址,使用什么来存放它的地址呢?答案是:二级指针。 关于二级指针的运算 *pp先解引用,对pp中的地址进行访问,访问的就是p **pp, 先通过*pp找到p,再对p进行解引用,访问的就是a 指针数组,顾名思义,它应该是一个数组,是用

    2024年02月04日
    浏览(106)
  • C语言深入理解指针(非常详细)(二)

    指针的基本运算有三种,分别是: • 指针±整数 • 指针-指针 • 指针的关系运算 因为数组在内存中是连续存放的,比如int类型的数组,每个元素相差4个字节,因此我们只需要知道首元素的地址就可以通过加减的方式找到后面元素的地址 。 概念:野指针就是指针指向的位置

    2024年02月10日
    浏览(41)
  • C语言深入理解指针(非常详细)(一)

    在将内存和地址时我们先举一个生活中的例子: 假设有⼀栋宿舍楼,把你放在楼里,楼上有100个房间,但是房间没有编号,你的⼀个朋友来找你玩, 如果想找到你,就得挨个房子去找,这样效率很低,但是我们如果根据楼层和楼层的房间的情况,给每个房间编上号,如: 有

    2024年02月10日
    浏览(37)
  • C语言深入理解指针(非常详细)(四)

    字符指针在之前我们有提到过,(字符)(指针)前面的字符代表着存储的元素为字符类型,而指针则是表示这存储的方式。 写法为char * 一般使用的方式如下: 还有一种使用方式如下: 值得注意的是: 代码 const char pstr = “hello jack.”; 特别容易以为是把字符串 hello jack 放到

    2024年02月09日
    浏览(53)
  • 【C语言基础】:深入理解指针(三)

    指针系列回顾 : 【C语言基础】:深入理解指针(一) 【C语言基础】:深入理解指针(二) 一、冒泡排序 冒泡排序的核心思想就是:两两相邻的元素进行比较。 可以看到,这段代码对arr数组进行了排序,但这个代码还有一些缺陷,那就是无论数组内部的元素是否有序,他都会循

    2024年03月10日
    浏览(40)
  • C语言——从头开始——深入理解指针(1)

     一.内存和地址 我们知道计算上CPU(中央处理器)在处理数据的时候,是通过地址总线把需要的数据从内存中读取的,后通过数据总线把处理后的数据放回内存中。如下图所示: 计算机把内存划分为⼀个个的 内存单元 ,每个内存单元的大小取1个字节( 1个字节(Byte)=8个比特

    2024年02月21日
    浏览(44)
  • 【C语言】指针的入门篇2,深入理解指针和数组的关系

    欢迎来CILMY23的博客喔,本期系列为【C语言】指针的入门篇2,深入理解指针和数组的关系,图文讲解指针和数组关系的知识,带大家理解指针和数组的关系,以及指针+数组的用法,感谢观看,支持的可以给个赞哇。 前言 在上一篇博客中,我们了解了指针就是地址,并且把地

    2024年02月20日
    浏览(46)
  • C语言之指针篇【超详细讲解,带你层层深入理解指针】

    目录 一、关于指针 二、指针类型 1、整型指针的访问权限说明: 2、字符指针的访问权限说明: 3、指针的类型决定向前或向后一步走了多大距离 三、野指针相关知识 1、野指针的成因 ①指针未初始化 ②指针的越界访问 ③指针所指向的空间释放了 2、如何规避野指针 ①指针

    2024年02月02日
    浏览(38)
  • C语言中关于指针的理解及用法

    关于指针意思的参考: https://baike.baidu.com/item/%e6%8c%87%e9%92%88/2878304   指针 = 指针变量 = 地址  野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的) 以下是导致野指针的原因  在这里面*p没有初始化,所以默认为随机值,我们也把这样的指针叫做野指

    2024年01月16日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包