Cherno C++学习笔记 P43 对象生存周期

这篇文章我们讲一下对象的生存周期。这个也是一个很重要的问题,因为我们总说,编程其实就是在操纵内存,而知道了变量如何在栈上生存,以及我们如何利用这些特性来让我们的编程更加简单,我们才是真的理解了编程。我们都知道,在为变量分配内存的时候,我们可以选择栈上分配,也可以选择堆上分配,由于在堆上分配需要我们手动清理内存,所以相当于我们可以自己决定这个变量的生存时间,因此我们主要了解栈上对象的生存周期。

如何理解栈?我们可以认为栈就像一个书堆,我们新来的书要放在上面,但是如果我们想要取出一本书,也要从上方取走。在栈上创建变量的时候,我们相当于把这个变量的作用域一整个当成一本书,放在了这个书堆的上方;离开了作用域的时候,相当于我们取走了这本书,那么书里面的变量也连带着一起被取走了,自然也就相当于里面的变量消失了。

这种变量会随着作用域的结束而一起销毁的事实,是好事也是坏事,坏处在于我们有的时候忘记了这件事情,想要使用已经结束的作用域中的变量,或者是使用其指针/引用,会发现出错;好处是我们可以利用这样一个特性,让我们在堆上建立变量的时候,不需要delete也可以实现自动销毁。

那么什么叫做作用域?我们的if while循环体,空大括号,函数定义,类定义等都是作用域。我们可以看一个简单的例子展示一下离开作用域之后为什么就会销毁变量,以一个Entity类为例:

#include<iostream>
#include<string>

class Entity {
public:
	Entity() {
		std::cout << "New Entity is Constructed!" << std::endl;
	}
	~Entity() {
		std::cout << "Old Entity is Destroyed!" << std::endl;
	}
};

int main() {
	{
		Entity e;
	}
	std::cin.get();
}

然后我们进入调试模式,可以看到当我们离开作用域了的时候,如下所示:

此时我们已经完成了构建与析构这个实例:

这样我们就可以看到,在作用域结束的时候,我们的对象就已经被摧毁了。

但是如果我们在堆上建立这个变量,比如中间作用域内我们改成这个样子:

{
	Entity* e = new Entity;
}

我们再调试可以发现,在我们离开作用域之后,析构函数依然没有被调用,直到整个程序结束,我们才会调用析构函数来销毁这个变量。

正是因为栈建立的变量有这样的特点,所以如果我们在一个函数中构建变量并返回,那么如果是栈上的变量,就会给我们报错:

static int* Function() {
	int a[50];
	return a;
}

比如像这样的代码,如果我们离开了函数,这个数组其实就已经消失了,我们再返回这个数组的指针也就毫无意义了。不过需要注意的是,如果只是返回值,那么我们用一个新变量来承接这个值,那是没有问题的,但是返回指针通常是有问题的,因为指针指向的那个内容已经随着离开作用域狗带了,要这个指针没有任何意义了。

那么我们如何避免这种情况的发生?整体上有两种方法,第一个是我们在函数内用new关键字在堆上分配内存,这样我们只要不手动清理,这个内存就会一直被分配;第二个是我们可以在外面写一个全局变量,然后把值赋给这个全局变量并返回,这样也可以保证变量一直存在。

但是如果我们善于利用栈上的变量离开了作用域就会被销毁这个特点,其实我们是可以让我们的代码更加简洁的,其中一个重要的作用就是自动化new&delete,可以有效防止我们经常忘记写delete导致内存泄漏的问题。其实这就是最常用的智能指针,作用域指针的设计思路。我们可以自己写这样一个指针类来看看会发生什么:

class ScopedPtr {
public:
	Entity* ptr;
public:
	ScopedPtr(Entity* ptr) {
		this->ptr = ptr;
	}
	~ScopedPtr() {
		delete ptr;
	}
};

我们可以看到,这样一个指针类当中,我们在析构函数当中选择使用delete关键字来释放内存,这样的好处就是,当我们ScopedPtr类型的变量被销毁时,连带着也会释放内存,我们来看一下实际的应用情况:

{
	ScopedPtr p = new Entity;
}

我们可以发现,它的定义方式和常规的new非常类似,但是当我们离开作用域之后,就会发现new分配的内存已经被释放。因为虽然new Entity是在堆上分配内存,但是ScopedPtr类是在栈上分配的内存,在离开作用域之后,它就会调用自己的析构函数,而它的析构函数,我们自己写的,刚刚好又是释放new Entity所分配的内存,所以我们可以不用再额外去写delete,就实现了离开作用域之后自动释放new分配的内存。

以上其实就是智能指针所做的事情,我们后面还会详细讲解智能指针,希望大家喜欢!

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

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

相关文章

02、10个富士胶片模拟的设置

二色彩 1、色彩的加减控制全局的饱和度增减&#xff1b; 2、色彩效果只提升暖色系饱和度&#xff1b; 3、FX蓝色大幅度提升蓝色系饱和度&#xff1b; 4、三个参数都不改变颜色的色相。 2.1 色彩 色彩调整的是拍摄画面整体的色彩饱和程度 2.2色彩效果 调整的是画面中暖色…

【Unity3D】ILRuntime学习记录一

Unity 2019.4.0f1 导入ILRuntime 2.1.0版本 项目目录/Packages/manifest.json添加如下代码&#xff1a; {"scopedRegistries":[{"name":"ILRuntime","url":"https://registry.npmjs.org","scopes":["com.ou…

ECharts柱状图-柱图38,附视频讲解与代码下载

引言&#xff1a; 在数据可视化的世界里&#xff0c;ECharts凭借其丰富的图表类型和强大的配置能力&#xff0c;成为了众多开发者的首选。今天&#xff0c;我将带大家一起实现一个柱状图图表&#xff0c;通过该图表我们可以直观地展示和分析数据。此外&#xff0c;我还将提供…

2024年12月19日Github流行趋势

项目名称&#xff1a;ByteByteGoHq / system-design-101 项目维护者&#xff1a;slam, LombardiDaniel, Stephanvs, alastairp, lucasberti 等项目介绍&#xff1a;使用视觉和简单术语解释复杂的系统。帮助你准备系统设计面试。项目star数&#xff1a;66,527项目fork数&#xf…

Elasticsearch:什么是信息检索?

信息检索定义 信息检索 (IR) 是一种有助于从大量非结构化或半结构化数据中有效、高效地检索相关信息的过程。信息&#xff08;IR&#xff09;检索系统有助于搜索、定位和呈现与用户的搜索查询或信息需求相匹配的信息。 作为信息访问的主要形式&#xff0c;信息检索是每天使用…

机械鹦鹉与真正的智能:大语言模型推理能力的迷思

编者按&#xff1a; 大语言模型真的具备推理能力吗&#xff1f;我们是否误解了"智能"的本质&#xff0c;将模式匹配误认为是真正的推理&#xff1f; 本文深入探讨了大语言模型&#xff08;LLMs&#xff09;是否真正具备推理能力这一前沿科学问题&#xff0c;作者的核…

day-21 内核链表以及栈

1.昨日作业 1.删除指定节点 找到删除就完事了&#xff0c;双向可以停在删除处。 /***************************** 功能&#xff1a;删除指定结点&#xff08;通过姓名&#xff09;* 参数&#xff1a;phead&#xff1b;oldname; * 返回&#xff1a;成功0&#xff0c;失-1&…

深入剖析MyBatis的架构原理

架构设计 简要画出 MyBatis 的架构图 >> ​​ Mybatis 的功能架构分为哪三层&#xff1f; API 接口层 提供给外部使用的接口 API&#xff0c;开发人员通过这些本地 API 来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。MyBatis 和数据库的…

Figma插件:提高设计工作效率

Figma作为一款当前流行的设计工具&#xff0c;其受欢迎程度的飙升与2020年疫情后的远程工作趋势密切相关。许多设计团队开始转向线上办公模式&#xff0c;这时&#xff0c;Figma的协作功能就显得尤为重要&#xff0c;促使众多设计师从Sketch等传统设计软件转向Figma。 Figma是…

Hive其一,简介、体系结构和内嵌模式、本地模式的安装

目录 一、Hive简介 二、体系结构 三、安装 1、内嵌模式 2、测试内嵌模式 3、本地模式--最常使用的模式 一、Hive简介 Hive 是一个框架&#xff0c;可以通过编写sql的方式&#xff0c;自动的编译为MR任务的一个工具。 在这个世界上&#xff0c;会写SQL的人远远大于会写ja…

Qt之自定义标题栏拓展(十)

Qt开发 系列文章 - user-defined-titlebars&#xff08;十&#xff09; 目录 前言 一、方式一 1.效果演示 2.创建标题栏类 3.可视化UI设计 4.定义相关函数 5.使用标题栏类 二、方式二 1.效果演示 2.创建标题栏类 3.定义相关函数 1.初始化函数 2.功能函数 3.窗口关…

鱼跃医疗获评2024年国家级“绿色工厂”,以绿色制造树立行业标杆

近日&#xff0c;工业和信息化部公布了2024年度绿色制造名单&#xff0c;鱼跃医疗凭借在绿色制造和可持续发展方面的卓越表现&#xff0c;成功入选并获评国家级“绿色工厂”。 “绿色工厂”是工信部为贯彻落实国家《工业绿色发展规划》&#xff0c;加快推动绿色制造体系建设&a…

【数据集】玻璃门窗缺陷检测数据集3085张5类YIOLO+VOC格式

数据集格式&#xff1a;VOC格式YOLO格式 压缩包内含&#xff1a;3个文件夹&#xff0c;分别存储图片、xml、txt文件 JPEGImages文件夹中jpg图片总计&#xff1a;3085 Annotations文件夹中xml文件总计&#xff1a;3085 labels文件夹中txt文件总计&#xff1a;3085 标签种类数&am…

一、LRU缓存

LRU缓存 1.LRU缓存介绍2.LRU缓存实现3.LRU缓存总结3.1 LRU 缓存的应用3.2 LRU 缓存的优缺点 1.LRU缓存介绍 LRU是Least Recently Used 的缩写&#xff0c;意为“最近最少使用”。它是一种常见的缓存淘汰策略&#xff0c;用于在缓存容量有限时&#xff0c;决定哪些数据需要被删…

【视频生成模型】——Hunyuan-video 论文及代码讲解和实操

&#x1f52e;混元文生视频官网 | &#x1f31f;Github代码仓库 | &#x1f3ac; Demo 体验 | &#x1f4dd;技术报告 | &#x1f60d;Hugging Face 文章目录 论文详解基础介绍数据预处理 &#xff08;Data Pre-processing&#xff09;数据过滤 (Data Filtering)数据标注 (Data…

【C++】函数计算题解论

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目描述&#x1f4af;思路解析3.1 函数的递归定义3.2 边界条件控制3.3 记忆化搜索 &#x1f4af;C实现代码&#x1f4af;添加解释&#x1f4af;小结 &#x1f4af;前言 在…

低温高海拔大载重无人机吊运技术详解

低温高海拔大载重无人机吊运技术是一项复杂而先进的技术&#xff0c;它结合了无人机的飞行控制、吊装系统的操作以及特殊环境下的适应性等多个方面。以下是对该技术的详细解析&#xff1a; 一、无人机基础知识与结构特点 低温高海拔大载重无人机通常采用旋翼设计&#xff0c;…

Java设计模式 —— 【结构型模式】适配器模式(类的适配器、对象适配器、接口适配器)详解

文章目录 基本介绍一、类的适配器二、对象适配器三、接口适配器总结 基本介绍 生活中有很多例子&#xff1a; 不同国家的插座接口不同&#xff0c;需要转换器&#xff1b;家用电源220V&#xff0c;手机只接受5V充电&#xff0c;需要转换器&#xff1b;读卡器&#xff0c;拓展…

系列2:基于Centos-8.6Kubernetes 集成GPU资源信息

每日禅语 自省&#xff0c;就是自我反省、自我检查&#xff0c;自知己短&#xff0c;从而弥补短处、纠正过失。佛陀强调自觉觉他&#xff0c;强调以达到觉行圆满为修行的最高境界。要改正错误&#xff0c;除了虚心接受他人意见之外&#xff0c;还要不忘时时观照己身。自省自悟之…

leetcode17:电话号码的字母组合

给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例 1&#xff1a; 输入&#xff1a;digits "23" 输出&#…