首页 > 其他分享 >智能指针

智能指针

时间:2023-12-26 20:33:12浏览次数:22  
标签:std include 智能 shared unique ptr 指针

智能指针

C++中的智能指针分为4类,分别是:

  1. 共享指针(std:shared_ptr)
  2. 独占指针(std::unique_ptr)
  3. auto_ptr
  4. weak_ptr

其中,auto_ptr已被C++11标准摒弃,C++17标准已经不可用。

智能指针的出现,能够很好的解决原始指针因为忘记释放内存而导致的一系列问题,或是因为删除不彻底而形成的空悬指针问题。

接下来,我将分别介绍不同的智能指针及其具体的使用方法

shared_ptr

shared_ptr的声明

shared_ptr声明在头文件memory中,且存在于命名空间std中

其基本模板

template <class T> class shared_ptr;

这里并不是很好理解,可以换个方式看

std::shared_ptr<typename T> ptr_name;
// 这里首先要声明命名空间std
// typename,即类型名称,不只是内置类型,也可以是用户自定义类型,如类类型
// ptr_name,即对象名称

下面演示如何声明一个shared_ptr类型的智能指针

#include <memory> //引入memory头文件

int main(void){
	std::shared_ptr<int> p;
}

shared_ptr的初始化

shared_ptr有多种重载的初始化方式,下面介绍几种常用的方法

  1. 直接初始化(调用了重载的构造函数):

shared_ptr的初始化只能由一个指针类型来完成,且一般是一个new开辟的动态内存的指针类型,直接初始化也正是调用了这种构造函数完成的初始化

template<typename T>
std::shared_ptr<T> p(new T()); //这里执行了值初始化
//如果类型T存在默认的构造函数,则会执行默认构造函数
  1. make_shared函数初始化:

相较于第一种方法,我更推荐第二种采用make_shared函数进行初始化的方法,原因如下:

使用make_shared创建的智能指针,可以免去new带来的额外内存花销,更加高效和安全
而且new开辟动态内存时,可能会发生开辟失败并抛出一个bad_alloc异常
这些都无疑提高了程序的性能

shared_ptr的使用

shared_ptr进行内存释放遵循一下原则:

  1. 当一个shared_ptr指针的引用计数为0时,进行对象的内存释放
  2. 当shared_ptr的生命周期结束时,进行内存释放,而无论该指针的引用计数是否为0

下面我将介绍一下有关shared_ptr的引用计数,这是智能指针实现智能释放内存的关键所在,每当对一个shared_ptr进行拷贝或引用操作时,该指针的引用计数递增1,这些指针共享同一块内存,所以该指针称为共享指针,每当有一个指针进行释放操作后,引用计数递减1,当引用计数为0时,即使生命周期还未结束,该指针指向的对象一样会进行内存释放。

#include<iostream>
#include<memory>

class Func { //创建一个类,用以说明智能指针的释放时机和生命周期的关系
public:
	Func();
	~Func(); //声明构造和析构函数
};

Func::Func() {
	std::cout << "Func is built." << std::endl; //打印提示构造函数已被调用
}

Func::~Func() {
	std::cout << "Func is destroyed." << std::endl; //打印提示析构函数已被调用
}

int main(void) {
	std::shared_ptr<Func> p1 = std::make_shared<Func>(); //创建一个shared_ptr类型指针
	std::shared_ptr<Func> p2(p1);
	std::shared_ptr<Func> p3(p1);
	std::shared_ptr<Func> p4(p1);
	std::shared_ptr<Func> p5(p1); //拷贝构造

  //use_count()用来统计一个对象被多少shared_ptr指针共享
	std::cout << p1.use_count() << std::endl; //结果为5

	p1.reset();
	p2.reset();
	p3.reset();
	p4.reset();
	p5.reset(); //空参数列表的reset函数用以释放shared_ptr指针的内存
	//当所有共享指针全部释放完成后,执行类的析构函数,尽管这些指针的生命周期还没有结束
  
	std::cout << "This is a signal." << std::endl; //在析构函数提示打印后才打印出来
	return 0;
}

//该程序结果如下:
//Func is built.
//5
//Func is destroyed.
/This is a signal.

uinque_ptr

unique_ptr的声明

与shared_ptr类似,unique_ptr的声明如下

#include <memory>
template<typename T>
std::unique_ptr<T> ptr_name;

unique_ptr的初始化

在C++14标准以前,并没有提供一个类似于make_shared的函数返回一个shared_ptr智能指针,C++14引入了make_unique函数,其功能与make_shared类似,都是返回一个相关类型的智能指针

#include <iostream>
#include <memory> //引入头文件
std::unique_ptr<int> p = std::make_unique<int>(10); //初始化方式与make_shared类似
std::cout<< *p <<std::endl;
//打印结果为10

同样,unique_ptr也支持使用new进行直接初始化

#include <memory>
#include <iostream>
#include <new>
std::unique_ptr<int> p(new int(10))
std::cout<< *p <<std::endl;
//打印结果为10

unique_ptr的使用

与shared_ptr不同,一个unique_ptr指针无法支持普通的拷贝或赋值操作,因为它是一个“独享”类型的指针

同shared_ptr一样,unique_ptr也支持通过reset函数来重置该对象;可以通过get函数来返回一个内置类型的指针,该指针是一个指向所管理对象的原始裸指针。

注意,在使用get函数返回的指针时,当智能指针被销毁时,该指针仍然存在,有可能导致空悬指针的出现,所以应当谨慎使用get函数返回的指针。

此外,unique_ptr还支持release函数,通过这个函数,可以改变unique_ptr的指向,举例如下:

#include <iostream>
#include <memory>
#include <new>

int main(void) {
	std::unique_ptr<int> p = std::make_unique<int>(10);
	std::unique_ptr<int> q;
	std::cout << "p = " << *p << std::endl;
	//std::cout << "q = " << *q << std::endl; // 无法执行,这是一个未定义行为
	auto n_p = p.release(); // n_p存储了p指针的原始数据,release之后,该智能指针被销毁
  p = nullptr; // 注意,这里一定要将p指针置空,否则会出现空悬指针,引发内存泄露风险
  //p.reset();
	q = std::make_unique<int>(*n_p); // 将数据赋予新指针q
	//std::cout << "p = " << *p << std::endl; // release之后,同样无法调用,也是一个未定义行为
	std::cout << "q = " << *q << std::endl;

	return 0;
}
// 结果为:
//10
//10
// 进行了一个数据传递

weak_ptr(弱引用智能指针)

weak_ptr的声明

该指针声明同前面一样,不再赘述

#include<memory>
std::weak_ptr<int> w_p;

weak_ptr的初始化

该指针的初始化必须与shared_ptr指针相关联

std::shared_ptr<int> p = std::make_shared<int>(20);
std::weak_ptr<int> w_p(p); // 声明了一个shared_ptr,并以它初始化了一个weak_ptr指针

weak_ptr的使用

weak_ptr不同于上述两种智能指针,它本身并没有重载*或->运算符,所以它是无法直接访问其指向的对象的,但我们可以通过函数lock来访问weak_ptr指向的shared_ptr对象,如果shared_ptr存在,则返回一个shared_ptr类型,否则返回一个false

#include<iostream>
#include<memory>
#include<new>

int main(void) {
	std::shared_ptr<int> p = std::make_shared<int>(10);
	std::weak_ptr<int> w_p = p; // 使用一个shared_ptr初始化weak_ptr指针
	std::cout << "The shared_ptr value is " << *p << std::endl; 
  // 引用计数为1
	std::cout << "The number of reference is " << p.use_count() << std::endl;
	// std::cout << *w_p << std::endl;
	if (w_p.lock()) { // 检查shared_ptr指针的存在性
		std::cout << "The weak_ptr value is " << *w_p.lock() << std::endl;
    // 返回一个shared_ptr指针,所以可以进行解引用操作
	}

	return 0;
}


标签:std,include,智能,shared,unique,ptr,指针
From: https://blog.51cto.com/u_16271511/8986984

相关文章

  • 指针
    指针---不同指针类型的区别指针类型决定了指针进行解引用操作的时候,能够访问空间的大小指针+1代表了不同的类型+1跳过的不同字节eg:#define_CRT_SECURE_NO_WARNINGS1#include<stdio.h>intmain(){ inta=0x11223344; /*int*pa=&a;//访问前四个 *pa=0;*/ char*pc......
  • AR眼镜解决方案_AR智能硬件方案|显示方案|光学方案
    AR眼镜硬件方案设计主要以满足客户需求和功能为核心进行定制。设计过程包括芯片平台选型、主板尺寸大小、内存、电池容量以及各种功能的传感器、显示光学模组、摄像头、接口、按键、充电等部分的实现,同时考虑整机的结构、散热设计,以及双目AR眼镜、单目智能眼镜、全息头盔等多种......
  • 程序员视角体验快速搭建智能客服中心
    前言AmazonConnect是亚马逊云科技今年下半年刚推出的全渠道云联络中心服务,仅需简单几步就可以设置属于自己的联系中心,并可以添加任何地方的客服,让它和用户沟通交流。企业级使用者可以通过使用全渠道通信来给企业的客户创建超个性化的体验。另外,据我所知,亚马逊云科技的AmazonC......
  • 智能监测/检测系统EasyCVR国标接入无法播放是什么原因?该如何解决?
    安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力,也具备接入AI智能分析的......
  • AI智能分析平台/可视化监控云平台EasyCVR邮箱验证功能的实现操作
    视频汇聚/视频云存储/集中存储/视频监控管理平台EasyCVR能在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,实现视频资源的鉴权管理、按需调阅、全网分发、云存储、智能分析等,视频智能分析平台EasyCVR融合性强、开放度高、部署轻快,在智慧工地、智慧园区、智慧......
  • AI智能分析平台/可视化监控云平台EasyCVR邮箱验证功能的实现操作
    视频汇聚/视频云存储/集中存储/视频监控管理平台EasyCVR能在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,实现视频资源的鉴权管理、按需调阅、全网分发、云存储、智能分析等,视频智能分析平台EasyCVR融合性强、开放度高、部署轻快,在智慧工地、智慧园区、智慧......
  • 智能监控平台/视频共享融合系统EasyCVR海康设备国标GB28181接入流程
    TSINGSEE青犀视频监控汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力,也具备接入AI智能分析的能力,包括对人、车、......
  • 测试开发 | 自然语言处理基础:从文本到智能
    自然语言处理(NaturalLanguageProcessing,简称NLP)是人工智能领域中一项关键技术,旨在让计算机理解、处理和生成人类语言。NLP使得计算机能够读懂、理解和产生文本数据,为机器与人之间的沟通搭建了桥梁。本文将介绍自然语言处理的基础知识,包括其定义、主要任务和关键技术。什么是自然......
  • 测试开发 | 探索人工智能图像生成的奇妙世界
    摘要:人工智能图像生成是当今科技领域中备受瞩目的前沿技术之一,它借助深度学习和神经网络等先进技术,使计算机系统能够学习并创造出逼真、想象力丰富的图像。本文将深入探讨人工智能图像生成的原理、应用领域以及未来发展趋势。1.人工智能图像生成的原理人工智能图像生成的核心原理......
  • 测试开发 | 人工智能目标检测
    摘要:人工智能目标检测是计算机视觉领域的一项重要技术,通过深度学习和先进算法,使计算机系统能够自动识别并定位图像中的目标。本文将深入探讨人工智能目标检测的原理、应用领域以及未来发展的前景。1.人工智能目标检测的原理人工智能目标检测的核心在于使用深度学习模型,其中卷积神......