《C++ Primer 第五版 中文版》第12章 动态内存【阅读笔记 + 个人思考】

news2024/12/23 19:03:02

《C++ Primer 第五版 中文版》第12章 动态内存【阅读笔记 + 个人思考】

    • 12.1 动态内存与智能指针
      • 12.1.1 shared_ptr类

静态内存包括:初始化只读数据段,初始化读写数据段,未初始化数据和常量数据段。

详细在下面博客总结:
Linux系统下C++程序运行时的内存布局及存储内容,生命周期,初始化时机详解。

智能指针的作用:一个动态内存空间对象应该被释放时,指向它的智能指针可以确保自动释放它。

12.1 动态内存与智能指针

运算符new:在动态内存为对象分配空间,返回指向该对象的指针。(是否进行初始化可选)

代码演示:当你使用new来分配内存但不提供初始化值时,分配的对象将拥有未定义的初始值(对于基本类型)。如果是类对象,将调用默认构造函数进行初始化。

#include <iostream>

int main() {
    // 为int分配内存,但不初始化,值未定义,访问这些未初始化的值是不安全的
    int* pInt = new int;

    // 为double分配内存,但不初始化,值未定义,访问这些未初始化的值是不安全的
    double* pDouble = new double;

    // 记得释放内存
    delete pInt;
    delete pDouble;

    return 0;
}

代码演示:使用new时,可以通过在类型后面添加圆括号()或大括号{}来提供初始化值。

#include <iostream>

int main() {
    // 为int分配内存,并初始化为0
    int* pInt = new int(0);

    // 为double分配内存,并初始化为0.0
    double* pDouble = new double(0.0);

    // 使用列表初始化
    int* pIntList = new int{10};
    double* pDoubleList = new double{10.5};

    std::cout << "*pInt: " << *pInt << "\n";
    std::cout << "*pDouble: " << *pDouble << "\n";
    std::cout << "*pIntList: " << *pIntList << "\n";
    std::cout << "*pDoubleList: " << *pDoubleList << "\n";

    // 记得释放内存
    delete pInt;
    delete pDouble;
    delete pIntList;
    delete pDoubleList;

    return 0;
}

运行结果:
运行结果
详细值初始化和默认初始化参考:值初始化和默认初始化详解

delete:接受一个动态对象的指针,销毁该对象,释放与对象关联的内存空间。

内存泄露:没有释放内存。
引用非法内存的指针:有指针引用内存的情况下释放了内存空间。

(C++11)shared_ptr:共享所指对象。

(C++11)unique_ptr:独占所指对象。

(C++11)weak_ptr :指向 shared_ptr 管理的对象。
参考:有了 unique_ptr 和 shared_ptr,要weak_ptr 有什么用?

头文件 memory。

12.1.1 shared_ptr类

智能指针是模板,默认初始化的智能指针中保存着一个空指针。

解引用智能指针:返回它指向的对象。

条件判断中使用智能指针:检测是否为空。

shared_ptr 和 unique_ptr 都支持的操作:![shared_ptr 和 unique_ptr
shared_ptr 独有的操作:
shared_ptr 独有的操作
最安全的分配和使用动态内存的方法:调用 make_shared 标准库函数(分配对象并初始化,返回指向此对象的 shared_ptr。不传递任何参数,对象进行值初始化。定义在头文件 memory)。

代码演示:

#include <iostream>
#include <memory> // 包含std::shared_ptr及相关函数

class MyClass {
public:
    void classMethod() const {
        std::cout << "MyClass::classMethod() called" << std::endl;
    }
};

int main() {
    // 使用make_shared()方法创建std::shared_ptr
    std::shared_ptr<MyClass> sp1 = std::make_shared<MyClass>();

    // 判断shared_ptr是否为空
    if (sp1 != nullptr) {
        std::cout << "sp1 is not null" << std::endl;
    }

    // 解引用shared_ptr来调用对象的方法
    (*sp1).classMethod();

    // 使用->操作符调用对象成员函数
    sp1->classMethod();

    // 使用get()方法获取原始指针
    MyClass* p = sp1.get();
    std::cout << "Address of the object owned by sp1: " << p << std::endl;

    // 使用拷贝构造函数创建一个shared_ptr的副本
    std::shared_ptr<MyClass> sp2(sp1);
    std::cout << "use_count of sp1 after copying: " << sp1.use_count() << std::endl; // 输出引用计数

    // 使用赋值操作符
    std::shared_ptr<MyClass> sp3;
    sp3 = sp1;
    std::cout << "use_count of sp1 after assignment: " << sp1.use_count() << std::endl; // 输出引用计数

    // 使用unique()方法检查当前shared_ptr是否是对象唯一的所有者
    if (!sp1.unique()) {
        std::cout << "sp1 is not unique" << std::endl;
    }

    // 使用use_count()方法查看对象的引用计数
    std::cout << "use_count of sp1: " << sp1.use_count() << std::endl;

    // 使用swap()方法交换两个shared_ptr的内容
    std::shared_ptr<MyClass> sp4 = std::make_shared<MyClass>();
    std::cout << "Before swap, sp1 address: " << sp1.get() << ", sp4 address: " << sp4.get() << std::endl;
    sp1.swap(sp4);
    std::cout << "After swap, sp1 address: " << sp1.get() << ", sp4 address: " << sp4.get() << std::endl;

    // 当main()函数结束时, sp1, sp2, sp3, sp4将自动被析构,并且它们所拥有的对象也将被删除
    // 因为sp1, sp2, sp3指向同一个对象,所以只有当最后一个shared_ptr被销毁后对象才会被删除
    // sp4指向一个不同的对象,将独立于sp1, sp2, sp3进行析构

    return 0;
}

运行结果:
运行结果

引用计数增加:

  1. 拷贝 shared_ptr。
  2. 作为参数传递给函数。
  3. 作为函数返回值。

引用计数递减:

  1. 给 shared_ptr 赋予一个新值。
  2. shared_ptr被销毁(例如:局部 shared_ptr 离开作用域)。

引用计数为0, shared_ptr 释放所管理的对象。

析构函数:对象销毁时,释放对象所分配的资源。

使用动态生存期的资源的类:

  1. 程序不知道自己需要使用多少对象(容器类)。
  2. 程序不知道所需对象的准确类型。
  3. 程序需要在多个对象间共享数据。

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

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

相关文章

linux系统编程 socket part2

报式套接字 1.动态报式套接字2.报式套接字的广播3.报式套接字的多播4.UDP协议分析4.1.丢包原因4.2.停等式流量控制 接linux系统编程 socket part1 1.动态报式套接字 在之前的例子上&#xff0c;发送的结构体中的名字由定长改变长。可以用变长结构体。 变长结构体是由gcc扩展的…

加密算法概述:分类与常见算法

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 在信息安全领域&#xff0c;加密技术是保护数据不被未授权访问的关键手段。Java作为一种广泛使用的编程语言&#xff0c;提供了丰…

记录个人学习golang路线(如何学习golang,如何转golang)

最近好久没更&#xff0c;在看兔兔的博客&#xff0c;学习golang&#xff0c;兔兔的文章&#xff0c;有一定的编程经验 && 初学golang者&#xff0c;一定要看&#xff0c;如果是其他语言转golang&#xff0c;那就必须要看了&#xff0c;可以帮助你了解golang的语法&…

png转gif怎么做?一招在线转换gif动画

PNG是一种常见的图像文件格式&#xff0c;它支持无损压缩和透明背景&#xff0c;而GIF则是一种支持动画的图像文件格式。在某些情况下&#xff0c;我们可能希望将静态的PNG图像转换为动态的GIF图像&#xff0c;以增加图像的趣味性和吸引力。要将PNG图像转换为GIF图像&#xff0…

【3D reconstruction 学习笔记 第二部】

三维重建 3D reconstruction 4. 三维重建与极几何三角化&#xff08;线性解法&#xff09;三角化&#xff08;非线性解法&#xff09;多视图几何极几何极几何约束基础矩阵估计 5. 双目立体视觉重建6. 多视图重建7. SFM 系统设计8. SLAM系统设计 4. 三维重建与极几何 三角化&…

如何在CentOS7部署openGauss管理系统并实现固定公网地址连接

文章目录 推荐前言1. Linux 安装 openGauss2. Linux 安装cpolar3. 创建openGauss主节点端口号公网地址4. 远程连接openGauss5. 固定连接TCP公网地址6. 固定地址连接测试 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不…

存储级内存SCM:PCM对决ReRAM

在22年7月份有一件震惊存储圈的事情&#xff0c;那就是Intel说要放弃Optane产品线&#xff0c;包括PMEM和SSD两个方向都要放弃。存储圈看到听到这个消息也是一脸的茫然。 在Optane产品发布之前&#xff0c;大家针对DRAM和SSD之间的性能gap一直在苦苦找寻合适的产品。SCM存储级内…

【LeetCode】回溯

labuladong回溯 回溯算法秒杀所有排列-组合-子集问题 回溯 一个回溯问题&#xff0c;实际上就是遍历一棵决策树的过程&#xff0c;树的每个叶子节点存放着一个合法答案。你把整棵树遍历一遍&#xff0c;把叶子节点上的答案都收集起来&#xff0c;就能得到所有的合法答案。 站…

@SpringBootApplication和SpringApplication.run源码解析:

文章目录 一、SpringBootApplication和自动配置1、主要功能2、SpringBootConfiguration3、EnableAutoConfiguration4、ComponentScan5、Spring boot自动配置5.1、Configuration开启自动配置5.2、查看自动配置5.3、禁用自动配置 二、run()new SpringApplication&#xff08;&…

Redis常用命令!!!

一、String&#xff08;字符串&#xff09; 1、set 设置单个key的value set key value set name 小明 2、mset 设置多个key的value mset key1 value1 key2 value2mset name1 小美 name2 小帅 3、get 获取单个key的值 get key get name4、mget 获取多个key的值 mget key1 key2 k…

[XOA Code]Test-suite-RFC2544

Testsuite-RFC2544&#xff0c;微信公众号也在间断的更新中&#xff0c;博客码码字&#xff0c;节奏老是踩不对&#xff0c;没什么条理 难道要不破不立&#xff0c;要全部推倒了重新来吗&#xff0c;....5555 XOA-2544测试 Dataset.py from typing import Any, List, Tuple,…

3.Spring Bean

3.1 Bean的配置 Spring可以看作一个大型工厂&#xff0c;生产和管理Spring容器中的bean。如何使用这个工厂生产和管理bean&#xff0c;需要开发者将bean配置在Spring的配置文件中。Spring框架支持XML和Properties两种格式的配置文件&#xff0c;在实际开发中&#xff0c;常用X…

天府锋巢直播产业基地科学城核心区域

天府锋巢直播产业基地位于天府新区科学城板块&#xff0c;地理位置优越&#xff0c;交通便利&#xff0c;是集直播电商、创新创业、人才培养等多功能于一体的现代化成都直播基地。这里汇聚了众多优秀的直播电商企业和创业团队&#xff0c;为直播电商行业的发展注入了强大的动力…

算法打卡day27|贪心算法篇01|Leetcode 455.分发饼干、376. 摆动序列、53. 最大子序和

贪心算法理论基础 定义 贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 例如&#xff0c;有一堆不同数值的钞票&#xff0c;可以拿走十张&#xff0c;如果想达到最大的金额可以指定每次拿最大的&#xff0c;最终结果就是拿走最大数额的钱。 每次拿最大的就…

混合像元分解:Matlab如何帮助揭示地表组成?

光谱和图像是人们观察世界的两种方式&#xff0c;高光谱遥感通过“图谱合一”的技术创新将两者结合起来&#xff0c;大大提高了人们对客观世界的认知能力&#xff0c;本来在宽波段遥感中不可探测的物质&#xff0c;在高光谱遥感中能被探测。以高光谱遥感为核心&#xff0c;构建…

分享一道DFS常见题目 C++实现路径之谜

题目描述&#xff1a;路径之谜 小明冒充X星球的骑士&#xff0c;进入了一个奇怪的城堡。 城堡里边什么都没有&#xff0c;只有方形石头铺成的地面。 假设城堡地面是 n x n 个方格。【如图1.png】所示。 按习俗&#xff0c;骑士要从西北角走到东南角。 可以横向或纵向移动&…

3个新变化!2024年国家高新技术企业认定攻略

根据《党和国家机构改革方案》和《党中央、国务院议事协调机构优化调整方案》&#xff0c;经报党中央、国务院批准&#xff0c;现将工业和信息化部职责、机构、编制调整&#xff0c;2024年由工信部管理国家高新技术企业认定工作。 总的来说&#xff0c;通过对政策的研究和解读…

Leetcode 76 最小覆盖子串 java版

官网链接&#xff1a; . - 力扣&#xff08;LeetCode&#xff09; 1. 问题&#xff1a; 给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串&#xff0c;则返回空字符串 "" 。 注意&#xff1a; 对于 …

langchian入门四:LLM+Agents代理=贾维斯?让大模型拥有三头六臂

什么是Agent 在日常生活中,不难发现,chatgpt通过文本输入进行处理后返回的也是文本内容,就像是一个只有头的人,能听能思考能说话,但是无法行动.而Agent是一种能够自主决策、采取行动以达到某种目标的实体。被解释为"智能体"或者"代理". 代理的核心思想是…

Java全栈课程之Linux———基本属性

一、看懂文件属性 Linux系统是一种典型的多用户系统&#xff0c;不同的用户处于不同的地位&#xff0c;拥有不同的权限。为了保护系统的安全性&#xff0c;Linux系统对不同的用户访问同一文件&#xff08;包括目录文件&#xff09;的权限做了不同的规定。 在Linux中我们可以使…