【9】C++四个智能指针

1 智能指针的作用

智能指针的作用是管理一个指针,因为存在以下这种情况:申请的空间在函数结束时忘记释放,造成内存泄漏。所以智能指针的作用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间。对于编译器来说,智能指针实际上是一个栈对象,并非指针类型,在栈对象生命期即将结束时,智能指针通过析构函数释放有它管理的堆内存。所有智能指针都重载了“operator->”操作符,直接返回对象的引用,用以操作对象。访问智能指针原来的方法则使用“.”操作符。智能指针不等同与普通指针。

2智能指针分类

STL 一共给我们提供了四种智能指针:auto_ptr、unique_ptr、shared_ptr 和 weak_ptr,auto_ptr 是 C++98 提供的解决方案,C+11 已将其摒弃,并提出了 unique_ptr 作为 auto_ptr 替代方案。

3各种智能指针介绍

3.1 unique_ptr

目的:将对象限制为由一个所有者(指针)所有,因为多个所有权会使程序逻辑变得复杂(即只准有一个指针访问对象)
unique_ptr 的构造和移动:
在这里插入图片描述

unique_ptr的基本操作有:

// Automaticptr.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include <memory>//智能指针头文件

using namespace std;

struct Task {
	int mId;
	Task(int id) :mId(id) {
		std::cout << "Task::Constructor" << std::endl;
	}
	~Task() {
		std::cout << "Task::Destructor" << std::endl;
	}
};

int main()
{
	// 通过原始指针创建 unique_ptr 实例
	std::unique_ptr<Task> taskPtr(new Task(23));
	//通过 unique_ptr 访问其成员
	int id = taskPtr->mId;
	cout << id <<endl;
	
	//普通指针
	char str[] = "hjdjdt";
	char *ptr =str;
	cout << ptr << endl;
	//[1]unique_ptr
	//目的:将对象限制为由一个所有者所有,即一个指针指向一个对象,不容许多个指针指向一个对象
	//构造智能指针
	auto ptrA = make_unique<string>("guih"); //C++ 14 引入的新函数
	cout <<"智能指针 ptrA:" <<ptrA << endl;
	//cout << "智能指针 ptrA:" << ptrA.get << endl;
	//变更智能指针
	auto ptrB = move(ptrA);
	cout << "智能指针 ptrA:" << ptrA << endl;//ptrA被清空
	cout << "智能指针 ptrB:" << ptrB << endl;//ptrA被赋值给ptrB
	
	//创建空的智能指针
	unique_ptr<int> ptrC;
	//绑定动态对象,创建时没有赋值,需要重新绑定
	ptrC.reset(new int(3));
	
	//创建时指定动态对象
	unique_ptr<int> ptrD(new int(4));

	// 所有权的变化
	int *p_i = ptrD.release();	//释放所有权  
	unique_ptr<string> u_s(new string("abc"));

	//所有权转移(通过移动语义),u_s所有权转移后,变成“空指针” 
	unique_ptr<string> u_s2 = move(u_s); 

	//所有权转移 先释放在设置为空指针
	u_s2.reset(u_s.release());	

	//显式销毁所指对象,同时智能指针变为空指针。与u_s2.reset()等价
	u_s2 = nullptr;
	system("pause");
	return 0;
}

3.2 auto_ptr

auto_ptr 在 C++98 中引入,定义在头文件。其功能和用法类似于 unique_ptr,由 new expression 获得对象,在 auto_ptr 对象销毁时,他所管理的对象也会自动被 delete 掉。auto_ptr 从 C++98 使用至今,从 C++11 开始,引入unique_ptr 来替代 auto_ptr 。
替换的原因:
(1)安全考虑
避免因潜在的内存问题导致程序崩溃 。使用 unique_ptr 时编译出错,与 auto_ptr 一样,unique_ptr 也采用所有权模型,但在使用 unique_ptr 时,程序不会等到运行阶段崩溃
(2)unique_ptr 安全而且灵活
unique_ptr 是个临时右值,编译器允许拷贝语义,原始指针赋值给新的指针时,原始指针会自动被清除。
(3)扩展 auto_ptr 不能完成的功能
(a)unique_ptr 可放在容器中,弥补了 auto_ptr 不能作为容器元素的缺点。
(b)管理动态数组,因为 unique_ptr 有 unique_ptr<X[]> 重载版本,销毁动态对象时调用 delete[]。
(c)自定义资源删除操作(Deleter)。unique_ptr 默认的资源删除操作是 delete/delete[],若需要,可以进行自定义

3.3 shared_ptr

shared_ptr 是一个标准的共享所有权的智能指针,允许多个指针指向同一个对象。原理:shared_ptr维护了一个指向control block的指针对象,来记录引用个数。
shared_ptr 是为了解决 auto_ptr 在对象所有权上的局限性(auto_ptr 是独占的),在使用引用计数的机制上提供了可以共享所有权的智能指针,当然这需要额外的开销:
(1)shared_ptr 对象除了包括一个所拥有对象的指针外,还必须包括一个引用计数代理对象的指针;
(2)时间上的开销主要在初始化和拷贝操作上, * 和 -> 操作符重载的开销跟 auto_ptr 是一样;
(3)开销并不是我们不使用 shared_ptr 的理由,,永远不要进行不成熟的优化,直到性能分析器告诉你这一点。

3.4 weak_ptr

weak_ptr用于避免shared_ptr相互指向产生的环形结构,造成的内存泄漏。weak_ptr count是弱引用个数;弱引用个数不影响shared count和对象本身,shared count为0时则直接销毁。
weak_ptr 被设计为与 shared_ptr 共同工作,可以从一个 shared_ptr 或者另一个 weak_ptr 对象构造而来。weak_ptr 是为了配合 shared_ptr 而引入的一种智能指针,它更像是 shared_ptr 的一个助手而不是智能指针,因为它不具有普通指针的行为,没有重载 operator* 和 operator-> ,因此取名为 weak,表明其是功能较弱的智能指针。它的最大作用在于协助 shared_ptr 工作,可获得资源的观测权,像旁观者那样观测资源的使用情况。观察者意味着 weak_ptr 只对 shared_ptr 进行引用,而不改变其引用计数,当被观察的 shared_ptr 失效后,相应的 weak_ptr 也相应失效。

4 智能指针选择原则

(1)如果程序要使用多个指向同一个对象的指针,应选择shared_ptr。
(2)如果程序不需要多个指向同一个对象的指针,则可使用unique_ptr。

5 参考文献

C++ 智能指针详解
C++ STL 四种智能指针:https://blog.csdn.net/k346k346/article/details/81478223#comments
C++11的智能指针(常见面试问题):https://blog.csdn.net/xy_cpp/article/details/81750575?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智能指针C++用于管理动态分配的内存的一种机制。它们可以自动地在不再需要时释放内存,从而避免内存泄漏和悬挂指针的问题。 shared_ptr是一种引用计数智能指针,它可以跟踪有多少个shared_ptr指向同一个对象,并在没有引用时自动释放内存。当创建shared_ptr时,它会增加引用计数,当销毁或重置shared_ptr时,它会减少引用计数。只有当引用计数为0时,才会真正释放内存。\[1\]shared_ptr可以通过构造函数接受一个指向动态分配对象的指针来创建,也可以使用std::make_shared函数来创建。\[2\] unique_ptr是一种独占智能指针,它拥有对动态分配对象的唯一所有权。当unique_ptr被销毁时,它会自动释放内存。unique_ptr不能被复制,但可以通过std::move函数进行转移所有权。\[3\]unique_ptr可以通过构造函数接受一个指向动态分配对象的指针来创建。 weak_ptr是一种弱引用智能指针,它指向由shared_ptr管理的对象,但不会增加引用计数。weak_ptr可以用于解决shared_ptr的循环引用问题,因为它不会导致对象无法释放。\[1\]weak_ptr可以通过shared_ptr的构造函数来创建。 auto_ptr是C++11之前的一种智能指针,它类似于unique_ptr,但有一些限制和问题。auto_ptr在复制时会转移所有权,这可能导致悬挂指针的问题。因此,auto_ptr已经被unique_ptr取代,不推荐使用。 总结来说,shared_ptr是引用计数智能指针,unique_ptr是独占智能指针,weak_ptr是弱引用智能指针,而auto_ptr是已经过时的智能指针。它们各自有不同的用途和特点,可以根据具体的需求选择使用。 #### 引用[.reference_title] - *1* *2* *3* [C++11 解决内存泄露问题的智能指针:shared_ptr、unique_ptr、weak_ptr](https://blog.csdn.net/weixin_44120785/article/details/128714630)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值