当前位置: 首页 > article >正文

C++高频面试考点 -- 智能指针

C++高频面试考点 – 智能指针

C++11中引入智能指针的概念,方便堆内存管理。这是因为使用普通指针,容易造成堆内存泄漏,二次释放,程序发生异常时内存泄漏等问题。

智能指针在C++11版本之后提供,包含在头文件<memory>中,shared_ptrunique_ptrweak_ptrauto_ptr

  1. shared_ptr

    shared_ptr使用引用计数、每一个shared_ptr的拷贝都指向相同的内存。每使用它一次,内部的引用计数就加一,每析构一次,内部的引用计数就减一,减为0的时候,自动删除所指向的堆内存。shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁。

    智能指针是一个模板类,可以指定类型,传入指针通过构造函数初始化。也可以使用make_shared函数初始化。不能将指针直接赋值给一个智能指针,一个是类,一个是指针。

    例如:std::shared_ptr <int> p = new int(1);的写法是错误的。

  2. unique_ptr

    unique_ptr“唯一”拥有其所指对象,也就是独享所有权语义,同一时刻只能有一个unique_ptr指向给定对象(禁止通过拷贝语义、只有移动语义来实现)。相比于原始指针,unique_ptr用于其RAII的特性,使得在出现异常的情况下,动态资源能够得到释放。

    unique_ptr指针本身的生命周期:从unique_ptr指针创建时开始,直到离开作用域,离开作用域时,若其指向对象,则将其所指对象销毁。

    unique_ptr指针与其所知对象的关系:在智能指针生命周期内,可以改变智能指针所指对象,如创建智能指针时通过构造函数指定、通过reset方法重新指定、通过release方法释放所有权、通过移动语义转移所有权。

  3. weak_ptr

    weak_ptr是一种不控制对象生命周期的智能指针,它指向一个shared_ptr管理的对象,进行该对象的内存管理的是哪个强引用的shared_ptrweak_ptr设计的目的是为了配合shared_ptr而引入的一种智能指针来协助shared_ptr。这是因为引用计数有一个问题就是互相引用形成环,这样两个指针指向的内存都无法释放。需要weak_ptr来打破环形引用。如果一块内存被shared_ptrweak_ptr同时引用,当所有shared_ptr析构了之后,不管还有没有weak_ptr引用该内存,内存也会被释放。所以weak_ptr不保证它指向的内存一定时有效的,在使用之前使用函数lock()检查weak_ptr是否为空指针。

  4. auto_ptr

    auto_ptr主要是为了解决“有异常抛出时发生内存泄漏”的问题。因为发生异常而无法正常释放内存。

    auto_ptr不支持拷贝和赋值的操作,不能用在STL标准容器中。STL容器中的元素经常要支持拷贝、赋值的操作,在这过程中auto_ptr会传递所有权,所以不能在STL中使用

手撕shared_ptr

#pragma once
namespace my_shared_ptr 
{   template <typename T>class shared_ptr{private:/* data */T *m_data;int *m_count; //计数public:shared_ptr() : m_data(nullptr), m_count(nullptr) {}shared_ptr(T *data) : m_data(data) {if(data != nullptr) {m_count = new int(1);}}shared_ptr(const shared_ptr<T> & other) : m_data(other.m_data), m_count(other.m_count){// 拷贝构造函数if(m_data != nullptr){(*m_count) ++;}}shared_ptr(shared_ptr<T> && other) noexcept : m_data(other.m_data), m_count(other.m_count){// 移动构造函数other.m_data = nullptr;other.m_count = nullptr;}~shared_ptr(){if(m_data != nullptr) {(*m_count) --;if(*m_count <= 0){delete m_data;m_data = nullptr;delete m_count;m_count = nullptr;}}}T * get() const{return m_data;}void reset(T *data = nullptr){if(m_data == data){return;}if(m_data == nullptr) {if(data != nullptr){m_data = data;m_count = new int(1);}return;}(*m_count) --;if(*m_count <= 0) {delete m_data;m_data = nullptr;delete m_count;m_count = nullptr;}m_data = data;if(data != nullptr) {m_count = new int(1);}}int use_count() const{if(m_data == nullptr){return 0;}return *m_count;}bool unique() const{// 判断是否只有一个智能指针指向该对象if(m_data == nullptr){return false;}return *m_count == 1;}void swap(shared_ptr<T> & other){auto data = other.data;auto count = other.m_count;other.m_data = m_data;other.m_count = m_count;m_data = data;m_count = count;}T* operator -> () const{return m_data;}T& operator * () const{return *m_data;}explicit operator bool() const noexcept{return m_data != nullptr;}shared_ptr & operator = (const shared_ptr<T> & other){if(this == &other){return *this;}m_data = other.m_data;m_count = other.m_count;(*m_count)++;return *this;}shared_ptr & operator = (shared_ptr<T> && other) noexcept{if(this == &other) {return *this;}m_data = other.m_data;m_count = other.m_count;other.m_data = nullptr;other.m_count = nullptr;return *this;}};}

测试代码

#include <string>
#include <iostream>
#include "shared_ptr.h"
using namespace my_shared_ptr;class Test
{
private:std::string m_name;
public:Test(/* args */) = default;void name(const std::string & name);std::string get_name() const;~Test();
};Test::~Test()
{std::cout << "Test is deleted" << std::endl;
}void Test::name(const std::string & name) 
{m_name = name;
}std::string Test::get_name() const
{return m_name;
}int main() 
{auto p = new Test();shared_ptr <Test> sp(p);sp -> name("jack");std::cout << sp->get_name() << std::endl;std::cout << sp.use_count() << std::endl;shared_ptr <Test> sp2;sp2 = sp;std::cout << sp2.use_count() << std::endl;return 0;
}

相关文章:

C++高频面试考点 -- 智能指针

C高频面试考点 – 智能指针 C11中引入智能指针的概念&#xff0c;方便堆内存管理。这是因为使用普通指针&#xff0c;容易造成堆内存泄漏&#xff0c;二次释放&#xff0c;程序发生异常时内存泄漏等问题。 智能指针在C11版本之后提供&#xff0c;包含在头文件<memory>中…...

06 如何定义方法,掌握有参无参,有无返回值,调用数组作为参数的方法,方法的重载

1.调用方法 2.掌握有参函数 3.调用数组作为参数 一个例题&#xff1a;数组参数&#xff0c;返回值 方法的重载 两个例题&#xff1a;冒泡排序和九九乘法表的格式学习...

使用vscode MSVC CMake进行C++开发和Debug

使用vscode MSVC CMake进行C开发和Debug 前言软件安装安装插件构建debuug方案一debug方案二其他 前言 一般情况下我都是使用visual studio来进行c开发的&#xff0c;但是由于python用的是vscode&#xff0c;所以二者如果统一的话能稍微提高一点效率。 软件安装 需要安装的软…...

C# AutoMapper对象映射详解

引言 在现代软件开发中&#xff0c;特别是采用分层架构的应用程序&#xff0c;我们经常需要在不同的对象类型之间进行转换。例如&#xff0c;从数据库实体&#xff08;Entity&#xff09;转换为数据传输对象&#xff08;DTO&#xff09;&#xff0c;或者从视图模型&#xff08…...

Keil5 MDK LPC1768 RT-Thread KSZ8041NL uIP1.3.1实现UDP网络通讯(服务端接收并发数据)

作为服务端&#xff0c;嵌入式软件实现流程&#xff1a; [上位机A/B/C/...] ↓ UDP [uIP 协议栈接收] ↓ [udp_appcall()] |-> 复制数据 |-> 保存源IP/端口 |-> 推送到接收队列 …...

提升开发运维效率:原力棱镜游戏公司的 Amazon Q Developer CLI 实践

引言 在当今快速发展的云计算环境中&#xff0c;游戏开发者面临着新的挑战和机遇。为了提升开发效率&#xff0c;需要更智能的工具来辅助工作流程。Amazon Q Developer CLI 作为亚马逊云科技推出的生成式 AI 助手&#xff0c;为开发者提供了一种新的方式来与云服务交互。 Ama…...

20250523-BUG-E1696:无法打开元数据文件“platform.winmd(已解决)

BUG&#xff1a;E1696&#xff1a;无法打开元数据文件“platform.winmd&#xff08;已解决&#xff09; 最近在用VisualStudio2022打开一个VisualStudio2017的C老项目后报了这个错&#xff0c;几经周折终于解决了&#xff0c;以下是我用的解决方法&#xff1a; 将Debug从Win32改…...

职业规划:动态迭代的系统化路径

1. 底层逻辑:构建职业规划的3大支柱 1.1 价值观锚定 1.1.1 生涯幻游法 通过想象理想生活的场景,包括工作环境、时间分配、人际关系、经济状态等,明确自己内心真正渴望的生活和工作状态,为职业规划提供方向指引。 1.1.2 价值观筛选 使用「价值观筛选卡」从30个常见职业价值…...

redisson-spring-boot-starter 版本选择

以下是更详细的 Spring Boot 与 redisson-spring-boot-starter 版本对应关系&#xff0c;按照 Spring Boot 主版本和子版本细分&#xff1a; 1. Spring Boot 3.x 系列 3.2.x 推荐 Redisson 版本&#xff1a;3.23.1&#xff08;最新稳定版&#xff0c;兼容 Redis 7.x&#xf…...

Docker run -v 的 rw 和 ro 模式_docker ro

一、前言 在使用 Docker 启动容器时&#xff0c;通常需要将宿主机的文件或目录挂载到容器中&#xff0c;以便于管理配置、持久化数据和调试日志。本篇博客将重点介绍 -v/--volume 参数的使用方式、挂载权限&#xff08;rw 与 ro&#xff09;的区别&#xff0c;以及如何通过 do…...

CentOS相关操作hub(更新中)

CentOS介绍&#xff1a; CentOS&#xff08;Community Enterprise Operating System&#xff09;是基于 Red Hat Enterprise Linux&#xff08;RHEL&#xff09;源代码编译的开源企业级操作系统&#xff0c;提供与 RHEL 二进制兼容的功能 完全兼容 RHEL&#xff0c;可直接使用…...

@Column 注解属性详解

提示&#xff1a;文章旨在说明 Column 注解属性如何在日常开发中使用&#xff0c;数据库类型为 MySql&#xff0c;其他类型数据库可能存在偏差&#xff0c;需要注意。 文章目录 一、name 方法二、unique 方法三、nullable 方法四、insertable 方法五、updatable 方法六、column…...

基于 ESP32 与 AWS 全托管服务的 IoT 架构:MQTT + WebSocket 实现设备-云-APP 高效互联

目录 一、总体架构图 二、设备端(ESP32)低功耗设计(适配 AWS IoT) 1.MQTT 设置(ESP32 连接 AWS IoT Core) 2.低功耗策略总结(ESP32) 三、云端架构(基于 AWS Serverless + IoT Core) 1.AWS IoT Core 接入 2.云端 → APP:WebSocket 推送方案 流程: 3.数据存…...

unity在urp管线中插入事件

由于在urp下&#xff0c;打包后传统的相机事件有些无法正确执行&#xff0c;这时候我们需要在urp管线中的特定时机进行处理一些事件&#xff0c;需要创建继承ScriptableRenderPass和ScriptableRendererFeature的脚本&#xff0c;示例如下&#xff1a; PluginEventPass&#xf…...

前后端的双精度浮点数精度不一致问题解决方案,自定义Spring的消息转换器处理JSON转换

在 Java 中&#xff0c;Long 是一个 64 位的长整型&#xff0c;通常用于表示很大的整数。在后端&#xff0c;Long 类型的数据没有问题&#xff0c;因为 Java 本身使用的是 64 位的整数&#xff0c;可以表示的范围非常大。 但是&#xff0c;在前端 JavaScript 中&#xff0c;Lo…...

docker安装es连接kibana并安装分词器

使用Docker部署Elasticsearch、Kibana并安装分词器有以下主要优点&#xff1a; 1. 快速部署与一致性 一键式部署&#xff1a;通过Docker Compose可以快速搭建完整的ELK栈环境 环境一致性&#xff1a;确保开发、测试和生产环境完全一致&#xff0c;避免"在我机器上能运行…...

线性回归中涉及的数学基础

线性回归中涉及的数学基础 本文详细地说明了线性回归中涉及到的主要的数学基础。 如果数学基础很扎实可以直接空降博文: 线性回归&#xff08;一&#xff09;-CSDN博客 一、概率、似然与概率密度函数 1. 概率&#xff08;Probability&#xff09; 定义&#xff1a;概率是描述…...

如何计算VLLM本地部署Qwen3-4B的GPU最小配置应该是多少?多人并发访问本地大模型的GPU配置应该怎么分配?

本文一定要阅读我上篇文章&#xff01;&#xff01;&#xff01; 超详细VLLM框架部署qwen3-4B加混合推理探索&#xff01;&#xff01;&#xff01;-CSDN博客 本文是基于上篇文章遗留下的问题进行说明的。 一、本文解决的问题 问题1&#xff1a;我明明只部署了qwen3-4B的模型…...

PostgreSQL日常维护

目录 一&#xff1a;基本使用 1.登录数据库 2.数据库操作 2.1列出库 2.2创建库 2.3删除库 2.4切换库 2.5查看库大小 3.数据表操作 3.1 列出表 3.2创建表 3.3复制表 3.4删除表 4.模式操作命令 4.1创建模式 4.2默认模式 4.3删除模式 4.4查看所有模式 4.5 在指定…...

Attu下载 Mac版与Win版

通过Git地址下载 Mac 版选择对于的架构进行安装 其中遇到了安装不成功&#xff0c;文件损坏等问题 一般是两种情况导致 1.安装版本不对 2.系统权限限制 https://www.cnblogs.com/similar/p/11280162.html打开terminal执行以下命令 sudo spctl --master-disable安装包Git下载地…...

V2X协议|如何做到“车联万物”?【无线通信小百科】

1、什么是V2X V2X&#xff08;Vehicle-to-Everything&#xff09;即“车联万物”&#xff0c;是一项使车辆能够与周围环境实现实时通信的前沿技术。它允许车辆与其他交通参与者和基础设施进行信息交互。通过V2X&#xff0c;车辆不仅具备“远程感知”能力&#xff0c;还能在更大…...

【zookeeper】--部署3.6.3

文章目录 下载解压创建data和logs配置文件1)创建目录并且编辑 zoo.cfg2)接下来将 node01 的 ZooKeeper 所有文件拷贝至 node02 和 node03。推荐从 node02 和 node03 拷贝4&#xff09;最后 vim /etc/profile 配置环境变量&#xff0c;环境搭建结束。配完环境变量后 source /etc…...

[测试_3] 生命周期 | Bug级别 | 测试流程 | 思考

目录 一、软件测试的生命周期&#xff08;重点&#xff09; 1、软件测试 & 软件开发生命周期 &#xff08;1&#xff09;需求分析 &#xff08;2&#xff09;测试计划 &#xff08;3&#xff09;测试设计与开发 &#xff08;4&#xff09;测试执行 &#xff08;5&am…...

物联网(IoT)智能项目全景指南:技术构架、实现细节与应用实践

目录 一、物联网项目的核心组成和发展方向 1. 核心组成 2. 发展趋势 二、系统设计的详细流程 1. 需求分析与方案规划 2. 硬件方案深度设计 3. 软件架构设计 4. 方案示意图&#xff08;架构图&#xff09; 三、关键技术深度剖析 1. 传感器及其接口技术 2. 嵌入式MCU选…...

【Go】1、Go语言基础

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言的特点 Go语言由Google团队设计&#xff0c;以简洁、高效、并发友好为核心目标。 具有以下优点&#xff1a; 语法简单、学习曲线平缓&#xff1a;语法关键字很少&#xff0c;且…...

RabbitMQ ⑤-顺序性保障 || 消息积压 || 幂等性

幂等性保障 幂等性&#xff08;Idempotency&#xff09; 是计算机科学和网络通信中的一个重要概念&#xff0c;指的是某个操作无论被执行多少次&#xff0c;所产生的效果与执行一次的效果相同。 应用程序的幂等性&#xff1a; 在应用程序中&#xff0c;幂等性就是指对一个系统…...

java基础知识回顾1(可用于Java基础速通)考前,面试前均可用!

目录 一、初识java 二、基础语法 1.字面量 2.变量 3.关键字 4.标识符 声明&#xff1a;本文章根据黑马程序员b站教学视频做的笔记&#xff0c;可对应课程听&#xff0c;课程链接如下: 02、Java入门&#xff1a;初识Java_哔哩哔哩_bilibili 一、初识java Java是美国 sun 公…...

云原生CICD-Tekton入门到精通

文章目录 一、Tekton介绍二、Tekton组件介绍三、执行流程四、安装Tekton管道五、安装Tekton Dashboard六、安装Tekton Cli七、运行单Task八、运行流水线九、在流水线中使用secret十、taskSpec、taskRef、pipelineRef、pipelineSpec使用pipelineRef与taskRef结合使用(推荐)pipel…...

CMake跨平台编译生成:从理论到实战

一、引言 在当今软件开发中&#xff0c;跨平台开发已成为常态。无论是需要在Windows、Linux、macOS等多操作系统上运行&#xff0c;还是在不同的硬件架构&#xff08;如x86、ARM等&#xff09;间部署&#xff0c;跨平台编译生成都是一个无法回避的关键问题。CMake&#xff0c;…...

MCP 协议传输机制大变身:抛弃 SSE,投入 Streamable HTTP 的怀抱

在技术的江湖里&#xff0c;变革的浪潮总是一波接着一波。最近&#xff0c;模型上下文协议&#xff08;MCP&#xff09;的传输机制就搞出了大动静&#xff0c;决定和传统的服务器发送事件&#xff08;SSE&#xff09;说拜拜&#xff0c;转身拥抱 Streamable HTTP&#xff0c;这…...