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

《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. 程序需要在多个对象间共享数据。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

吴恩达机器学习-可选实验室:Softmax函数

文章目录 CostTensorflow稀疏类别交叉熵或类别交叉熵祝贺 在这个实验室里&#xff0c;我们将探索softmax函数。当解决多类分类问题时&#xff0c;该函数用于Softmax回归和神经网络。 import numpy as np import matplotlib.pyplot as plt plt.style.use(./deeplearning.mplstyl…

【数据结构】顺序表和链表详解顺序表和链表的实现

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;数据结构_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.线性表 1.1 顺序表 1.1.1 概念及结构 1.1.2 静态顺序表 1.1.3 动态顺序表 1.2 链表 1.2.1 链表的概念及结构 1.2.2 链表…

力扣HOT100 - 1. 两数之和

解题思路&#xff1a; 解法一&#xff1a;暴力 class Solution {public int[] twoSum(int[] nums, int target) {int n nums.length;for (int i 0; i < n; i)for (int j i 1; j < n; j) {if (target nums[i] nums[j])return new int[] { i, j };}return new int[…

pcl利用kdtree计算点云密度

点云密度挺需要的,很多时候需要知道点云密度才能进行下一步 这里利用kdtree计算点云密度 代码 结果 这里单位写错了&#xff0c;抱歉

Personal Website

Personal Website Static Site Generators hexo hugo jekyll Documentation Site Generator gitbook vuepress vitepress docsify docute docusaurus Deployment 1. GitHub Pages 2. GitLab Pages 3. vercel 4. netlify Domain 域名注册 freessl 域名解析域名…

【数据结构与算法】Kruskal最小生成树

原理 算法实现 主要函数&#xff1a; 查并集&#xff1a; find 点 x 的祖先edge的比较大小函数kruskal函数 #include<iostream> #include<algorithm>using namespace std;struct Edge{int a,b,w;}edg[200010]; int p[200010]; int n,m;bool compareEdg(const Ed…

Redis 教程系列之Redis 安装(二)

Windows 下安装 下载地址:Releases tporadowski/redis GitHub。 Redis 支持 32 位和 64 位。这个需要根据你系统平台的实际情况选择,这里我们下载 Redis-x64-xxx.zip压缩包到 C 盘,解压后,将文件夹重新命名为 redis。 打开文件夹,内容如下: 打开一个 cmd 窗口 使用 c…

Apache TinkerPop 与 Gremlin 快速介绍

TinkerPop &#xff0c;Gremlin TinkerPop 是一个 Apache 项目&#xff0c;它为图数据库提供了一个通用的图处理框架。Gremlin 是 TinkerPop 框架的一部分&#xff0c;它是一个图遍历语言&#xff0c;用于在图数据库中执行复杂的图遍历查询。 Apache TinkerPop Apache Tinker…

AI程序员革命:探析Devin的登场与编程未来

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

【前端Vue】HR-saas中台项目开发md文档第1篇:vuex基础-介绍,vuex基础-初始化功能【附代码文档】

HR-saas中台管理项目开发完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;vuex基础-介绍,vuex基础-初始化功能,vuex基础-state,vuex基础-mutations,vuex基础-actions,vuex基础-getters。项目课设计&#xff0c;人力资源的环境搭建vue-element-admin的了解和…

react native 键盘事件

在做修改密码功能是发现他的键盘第一次调起之后然后收起键盘焦点不会消失而且键盘也不会再调起来了 我门线引入需要的组件 import { StyleSheet, View, TextInput, Keyboard, TouchableWithoutFeedback, } from react-native; import React, {useEffect, useState, useRef} fr…

【数据结构】Java中Map和Set详解(含二叉搜索树和哈希表)

目录 Map和Set详解 1.二叉搜索树 2.Map常见方法 3.Set常见方法 4.哈希表 Map和Set详解 Map&#xff1a;一种键值对结构&#xff0c;hashMap中键和值均可以为空&#xff0c;hashTable中则不可以存放null值 Set&#xff1a;一种集合&#xff0c;不能存放重复元素&#xff0c…

解决前端跨域问题

前端跨域问题 该问题是由于前端的服务路径或端口和后台的不一致所导致的 Springboot跨域设置 import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; …

手撕算法-二叉树的层序遍历

描述 分析 层序遍历&#xff0c;需要用到队列。 代码 代码1&#xff1a;独立bfs函数 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(i…

(C语言)浮点数在内存中的存储详解

1. 浮点数 常见的浮点数&#xff1a;3.14159、 1E10等 &#xff0c;浮点数家族包括&#xff1a; float、double、long double 类型。 浮点数表示的范围&#xff1a; float.h 中定义. 2. 浮点数的存储 我们先来看一串代码&#xff1a; int main() {int n 9;float* pFloa…

BufferedInputStream解读

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java之IO流啦&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好习惯&am…

实现文本溢出提示效果

实现效果 本文的需求是文本溢出时显示省略号&#xff0c;鼠标移入文本时提示完整的文字内容。 实现代码 <div class"container" onmouseover"handleMouseEnter(this)">鼠标移入显示全部内容</div><style> .container {width: 100px;o…

力扣每日一题 2024/3/23 统计桌面上的不同数字

题目描述 用例说明 思路讲解 给定整数n&#xff0c;找出循环十亿天后桌上的数字。可以先通过一天来找找规律。 第一天 n%i1 &#xff08;1<i<n&#xff09;只有n-1符合.加入桌面 第二天(n-1)%i1 &#xff08;1<i<n-1&#xff09;只有n-2符合 加入桌面 依次类推…

第十三届蓝桥杯JavaB组省赛真题 - 星期计算

解题思路&#xff1a; 方法一&#xff1a; 20的22次方是一个比较大的数&#xff0c;long和int都装不下这么大的数&#xff0c;因此需要使用下面的方法&#xff0c;如果 a, b, p 都是整数&#xff0c;且 p 是正数&#xff0c;那么&#xff1a;(a * b) % p (a % p * b % p) % …

【C语言】linux内核pci_set_drvdata函数

一、讲解 该函数pci_set_drvdata是Linux内核中用于PCI设备的一个辅助函数&#xff0c;其主要作用是设置给定PCI设备的驱动程序私有数据。这个函数的参数包括一个指向pci_dev结构体的指针pdev&#xff0c;该结构体描述了一个PCI设备&#xff0c;以及一个void *类型的指针data&a…