侯捷 C++ 课程学习笔记:深入理解智能指针

news2025/3/10 10:02:26

文章目录

  • 每日一句正能量
  • 一、引言
  • 二、智能指针的核心概念
    • (一)std::unique_ptr
    • (二)std::shared_ptr
    • (三)std::weak_ptr
  • 三、学习心得
  • 四、实际应用案例
  • 五、总结

在这里插入图片描述

每日一句正能量

如果说幸福是一个悖论,那么,这个悖论的解决正存在于争取幸福的过程之中。其实有斗争,有苦恼,但是要希望尚存,就有幸福。

一、引言

侯捷老师的 C++ 系列课程一直是我学习 C++ 的重要指导。在众多知识点中,智能指针这一部分让我印象深刻。它不仅解决了传统指针的诸多痛点,还体现了现代 C++ 的设计理念。通过深入学习,我对智能指针有了更深刻的理解,并在实际项目中尝试应用,收获颇丰。

二、智能指针的核心概念

智能指针是现代 C++ 中用于自动管理动态分配内存的一种工具。它通过封装原始指针,利用 RAII(资源获取即初始化)机制,在对象生命周期结束时自动释放内存,从而避免了内存泄漏和悬空指针等问题。侯捷老师在课程中详细讲解了智能指针的几种类型,包括 std::unique_ptrstd::shared_ptrstd::weak_ptr,并强调了它们的使用场景和注意事项。

(一)std::unique_ptr

std::unique_ptr 是一种独占所有权的智能指针,它确保同一时间只有一个指针指向一块动态分配的内存。它的实现基于模板,支持自定义删除器,能够很好地管理动态分配的资源。侯捷老师通过代码示例展示了 std::unique_ptr 的使用方法,让我深刻理解了它的独占性和自动释放机制。

例如,在一个简单的场景中,我们可以通过 std::unique_ptr 管理动态分配的对象:

#include <memory>
#include <iostream>

class MyClass {
public:
    MyClass() { std::cout << "Object created\n"; }
    ~MyClass() { std::cout << "Object destroyed\n"; }
};

int main() {
    std::unique_ptr<MyClass> ptr(new MyClass());
    // 当 ptr 超出作用域时,自动调用析构函数释放资源
}

(二)std::shared_ptr

std::shared_ptr 是一种共享所有权的智能指针,允许多个指针指向同一块内存。它通过引用计数机制来管理资源的生命周期,当最后一个 std::shared_ptr 被销毁时,才会释放资源。侯捷老师特别强调了引用计数的开销以及循环引用问题,并通过实际案例展示了如何使用 std::weak_ptr 解决循环引用。

例如,在一个对象图中,两个对象相互引用时,很容易出现循环引用问题。通过 std::weak_ptr,我们可以打破这种循环引用:

#include <memory>
#include <iostream>

class B;

class A {
public:
    std::shared_ptr<B> bPtr;
    ~A() { std::cout << "A destroyed\n"; }
};

class B {
public:
    std::weak_ptr<A> aPtr; // 使用 weak_ptr 避免循环引用
    ~B() { std::cout << "B destroyed\n"; }
};

int main() {
    std::shared_ptr<A> aptr = std::make_shared<A>();
    std::shared_ptr<B> bptr = std::make_shared<B>();

    aptr->bPtr = bptr;
    bptr->aPtr = aptr; // 使用 weak_ptr 指向 A
}

(三)std::weak_ptr

std::weak_ptr 是一种弱引用指针,它不增加引用计数,但可以观察被 std::shared_ptr 管理的对象。它的主要用途是解决循环引用问题,同时也可以用于延迟加载等场景。侯捷老师通过对比 std::shared_ptrstd::weak_ptr 的使用场景,让我明白了它们的互补关系。

三、学习心得

通过学习侯捷老师的课程,我对智能指针有了更深入的理解。智能指针不仅是一种内存管理工具,更是一种现代 C++ 的设计理念。它让我们能够更安全、更高效地管理动态资源,减少内存泄漏和悬空指针等问题。

在学习过程中,我意识到智能指针的使用需要根据具体场景选择合适的类型。例如,当资源需要独占时,应使用 std::unique_ptr;当需要共享资源时,应使用 std::shared_ptr,并注意避免循环引用。此外,引用计数的开销也是需要考虑的因素之一。

侯捷老师强调的“少用裸指针”原则也让我受益匪浅。在现代 C++ 中,智能指针几乎可以替代所有裸指针的使用场景,这不仅提高了代码的安全性,还减少了内存管理的复杂性。通过实践,我逐渐养成了使用智能指针的习惯,这让我在编写 C++ 程序时更加得心应手。

四、实际应用案例

在实际项目中,我尝试将智能指针应用于一个简单的图形渲染引擎中。在这个项目中,我们需要管理大量的动态分配的图形对象,如纹理、模型和场景节点。使用智能指针可以确保这些对象在生命周期结束时自动释放资源,避免内存泄漏。

例如,我们定义了一个 Texture 类和一个 Model 类,它们都通过智能指针进行管理:

#include <memory>
#include <vector>
#include <iostream>

class Texture {
public:
    Texture() { std::cout << "Texture created\n"; }
    ~Texture() { std::cout << "Texture destroyed\n"; }
};

class Model {
public:
    Model() { std::cout << "Model created\n"; }
    ~Model() { std::cout << "Model destroyed\n"; }
    std::shared_ptr<Texture> texture;
};

int main() {
    std::shared_ptr<Model> model = std::make_shared<Model>();
    model->texture = std::make_shared<Texture>();

    // 当 model 超出作用域时,自动释放 Model 和 Texture 的资源
}

在这个案例中,std::shared_ptr 确保了 ModelTexture 的生命周期管理。当 model 超出作用域时,ModelTexture 的资源会被自动释放,避免了手动管理内存的复杂性和风险。

此外,我还尝试使用 std::weak_ptr 来管理场景图中的节点关系。通过弱引用,我们可以避免循环引用问题,同时确保节点的生命周期管理更加灵活。

五、总结

通过学习侯捷老师的 C++ 课程,我对智能指针有了更深刻的理解。智能指针不仅是现代 C++ 的重要特性,更是内存管理的有力工具。它通过 RAII 机制,解决了传统指针的诸多问题,让内存管理变得更加安全和高效。

在实际项目中,智能指针的应用也让我体会到了现代 C++ 的强大和便捷。通过合理使用 std::unique_ptrstd::shared_ptrstd::weak_ptr,我们可以更好地管理动态资源,减少内存泄漏和悬空指针等问题。侯捷老师的课程不仅让我掌握了知识,更让我学会了如何在实际项目中应用这些知识。

未来,我将继续深入学习侯捷老师的课程,探索更多现代 C++ 的特性和应用场景,不断提升自己的编程能力。


:本文内容仅为个人学习笔记,如有错误或不足之处,欢迎指正。

转载自:https://blog.csdn.net/u014727709/article/details/146026240
欢迎 👍点赞✍评论⭐收藏,欢迎指正

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2312630.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

访问不了 https://raw.githubusercontent.com 怎么办?

修改 Hosts 文件&#xff08;推荐&#xff09;​ 原理&#xff1a;通过手动指定域名对应的 IP 地址&#xff0c;绕过 DNS 污染。 步骤&#xff1a; 1、访问 IPAddress.com&#xff0c;搜索 raw.githubusercontent.com&#xff0c;获取当前最新的 IPv4 地址&#xff08;例如 1…

大模型工程师学习日记(十五):Hugging Face 模型微调训练(基于 BERT 的中文评价情感分析)

1. datasets 库核心方法 1.1. 列出数据集 使用 d atasets 库&#xff0c;你可以轻松列出所有 Hugging Face 平台上的数据集&#xff1a; from datasets import list_datasets# 列出所有数据集 all_datasets list_datasets()print(all_datasets)1.2. 加载数据集 你可以通过 l…

子数组、子串系列(典型算法思想)—— OJ例题算法解析思路

一、53. 最大子数组和 - 力扣&#xff08;LeetCode&#xff09; 算法代码&#xff1a; class Solution { public:int maxSubArray(vector<int>& nums) {// 1. 创建 dp 表// dp[i] 表示以第 i 个元素结尾的子数组的最大和int n nums.size();vector<int> dp(n…

Windows编程----进程的当前目录

进程的当前目录 Windows Api中有大量的函数在调用的时候&#xff0c;需要传递路径。比如创建文件&#xff0c;创建目录&#xff0c;删除目录&#xff0c;删除文件等等。拿创建文件的CreateFile函数做比喻&#xff0c;如果我们要创建的文件路径不是全路径&#xff0c;那么wind…

AVL树的介绍及实现

文章目录 &#xff08;一&#xff09;AVL的概念&#xff08;二&#xff09;AVL树的实现1.AVL树的结构2.AVL树的插入3.AVL树的查找 &#xff08;三&#xff09;检查一棵树是否是AVL树 &#xff08;一&#xff09;AVL的概念 AVL树是一棵高度平衡的二叉搜索树&#xff0c;通过控制…

快速生成viso流程图图片形式

我们在写详细设计文档的过程中总会不可避免的涉及到时序图或者流程图的绘制&#xff0c;viso这个软件大部分技术人员都会使用&#xff0c;但是想要画的好看&#xff0c;画的科学还是比较难的&#xff0c;现在我总结一套比较好的方法可以生成好看科学的viso图(图片格式)。主要思…

【极光 Orbit•STC8A-8H】03. 小刀初试:点亮你的LED灯

【极光 Orbit•STC8H】03. 小刀初试&#xff1a;点亮你的 LED 灯 七律 点灯初探 单片方寸藏乾坤&#xff0c;LED明灭见真章。 端口配置定方向&#xff0c;寄存器值细推敲。 高低电平随心控&#xff0c;循环闪烁展锋芒。 嵌入式门初开启&#xff0c;从此代码手中扬。 摘要 …

OSPF报文分析

OSPF报文分析 组播地址 224.0.0.0&#xff5e;224.0.0.255为预留的组播地址&#xff08;永久组地址&#xff09;&#xff0c;地址224.0.0.0保留不做分配&#xff0c;其它地址供路由协议使用&#xff1b; 224.0.1.0&#xff5e;238.255.255.255为用户可用的组播地址&#xff08;…

MySql性能(9)- mysql的order by的工作原理

全字段排序rowid排序全字段排序和rowid排序 3.1 联合索引优化 3.2 覆盖索引优化优先队列算法优化建议 5.1 修改系统参数 5.2 优化sql 1. 全字段排序 CREATE TABLE t ( id int(11) NOT NULL,city varchar(16) NOT NULL, name varchar(16) NOT NULL, age int(11) NOT NULL,addr v…

爬虫案例七Python协程爬取视频

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Python协程爬取视频 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 爬虫案例七协程爬取视频 提示&#xff1a;以下是本篇文章正文…

智慧城市智慧社区项目建设方案

一、项目背景 在全球化进程加速的今天&#xff0c;城市化问题日益凸显&#xff0c;传统的城市管理模式已难以满足现代社会对高效、智能化管理的需求。智慧城市和智慧社区的概念应运而生&#xff0c;其核心目标是通过信息技术手段&#xff0c;提升城市资源的利用效率&#xff0…

RabbitMQ高级特性--消息确认机制

目录 一、消息确认 1.消息确认机制 2.手动确认方法 二、代码示例 1. AcknowledgeMode.NONE 1.1 配置文件 1.2 生产者 1.3 消费者 1.4 运行程序 2.AcknowledgeMode.AUTO 3.AcknowledgeMode.MANUAL 一、消息确认 1.消息确认机制 生产者发送消息之后&#xff0c;到达消…

Java EE 进阶:Spring IoCDI

IOC的简单介绍 什么是Spring&#xff1f;Spring是一个开源的框架&#xff0c;让我们的开发更加的简单&#xff0c;我们可以用一句更加具体的话来概括Spring&#xff0c;就是Spring是一个包含众多工具方法的IOC容器。 简单介绍一下IOC&#xff0c;我们之前说过通过ReqestContr…

Java数据结构第二十期:解构排序算法的艺术与科学(二)

专栏&#xff1a;Java数据结构秘籍 个人主页&#xff1a;手握风云 目录 一、常见排序算法的实现 1.1. 直接选择排序 1.2. 堆排序 1.3. 冒泡排序 1.4. 快速排序 一、常见排序算法的实现 1.1. 直接选择排序 每⼀次从待排序的数据元素中选出最小的⼀个元素&#xff0c;存放在…

【算法day5】最长回文子串——马拉车算法

最长回文子串 给你一个字符串 s&#xff0c;找到 s 中最长的 回文 子串。 https://leetcode.cn/problems/longest-palindromic-substring/description/ 算法思路&#xff1a; class Solution { public:string longestPalindrome(string s) {int s_len s.size();string tmp …

《如何排查Linux系统平均负载过高》

【系统平均负载导读】何为系统平均负载&#xff1f;假设一台云服务主机&#xff0c;突然之间响应用户请求的时间变长了&#xff0c;那么这个时候应该如何去排查&#xff1f;带着这个问题&#xff0c;我们对“平均负载”展开深入的探讨和研究。 何为Linux系统的平均负载&#xf…

基于DeepSeek实现PDF嵌入SVG图片无损放大

1. PDF中效果图 2. 询问Deepseek进行代码书写&#xff0c;不断优化后结果 /*** SVG工具类&#xff0c;用于生成价格趋势的SVG图表*/ public class SvgUtils {// SVG画布尺寸private static final int WIDTH 800;private static final int HEIGHT 500;private static final i…

整型的不同类型和溢出

一、整数的不同类型 不同编程语言中的整数类型主要通过以下两个维度区分&#xff1a; 1. 存储大小 字节数&#xff1a;决定整数能表示的范围&#xff08;如 1字节8位&#xff09;。 常见类型&#xff1a; byte&#xff08;1字节&#xff09;、short&#xff08;2字节&#x…

使用express创建服务器保存数据到mysql

创建数据库和表结构 CREATE DATABASE collect;USE collect;CREATE TABLE info (id int(11) NOT NULL AUTO_INCREMENT,create_date bigint(20) DEFAULT NULL COMMENT 时间,type varchar(20) DEFAULT NULL COMMENT 数据分类,text_value text COMMENT 内容,PRIMARY KEY (id) ) EN…

小程序 wxml 语法 —— 41列表渲染 - 进阶用法

这一节讲解列表渲染的两个进阶用法&#xff1a; 如果需要对默认的变量名和下标进行修改&#xff0c;可以使用 wx:for-item 和 wx:for-item&#xff1a; 使用 wx:for-item 可以指定数组当前元素的变量名使用 wx:for-index 可以指定数组当前下标的变量名 将 wx:for 用在 标签上&…