【C++核心】内存、引用、函数

news2025/1/20 14:49:30

一、内存四区域

C++程序在执行时,将内存大方向划分为4个区域
程序运行前分为:

  • 代码区:存放函数体的二进制代码exe,由操作系统进行管理的

exe机器指令、共享、只读

  • 全局区:存放全局变量和静态变量以及常量(字符串常量(用“”引起来的) & 全局常量(放在全局中,用const修饰的))

全局变量、静态变量、常量。该区域的数据在程序结束后由操作系统释放

程序运行后:

  • 栈区:由编译器自动分配释放(不用程序员管理他的生或死), 存放函数的参数值(形参数据也会放在栈区),局部变量(函数内部的)等
  • 堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收

堆栈区

从硬件上说,堆和栈最终都是内存条上的若干存储单元,所以并没有什么不同。

但,由于很多CPU对压栈、出栈操作有硬件(指令)上的支持,所以在栈区分配/归还内存速度极快(相比之下,堆上分配简直是龟速);尤其是函数内部的局部变量,可以轻易与函数调用/返回绑定,因此几乎所有编译型语言都会在利用栈管理局部变量(而且会优先使用空闲的寄存器,所以几乎所有高级语言都是访问局部变量速度最快)。
栈内存是存取速度比堆要快,仅次于寄存器,栈数据可以共享。

不仅如此。由于栈内存分配/回收的特殊机制,使得同一函数内部的“局部变量”总是分配在同一段连续内存空间上的;那么引用这些局部变量就不太容易出现CPU缓存失效问题。

特点不同:堆内存是优先队列的一种数据结构,满足先进后出的性质,栈内存存取速度仅次于寄存器,栈数据可以共享。
范围不同:堆内存需要手动进行适当,如果不释放,会出现内存溢出的问题。栈内存会随着变量的作用域分配和释放。

栈区:
栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

​ 由编译器自动分配释放, 存放函数的参数值,局部变量等
​ 注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放

在这里插入图片描述
第一次可以打印正确的数据是因为编译器做了保留。
在func运行完之后就把存a的地址直接释放了,内存被释放,用p来*就是非法操作。


堆区:

​ 由程序员分配释放,若程序员不释放,程序结束时由操作系统回收
​ C ++中利用new操作符在堆区开辟数据

语法: new 数据类型
利用new创建的数据,会返回该数据对应的类型的指针
delete后面加[]才能告诉编译器你要删除的是一系列的内存空间,而不是arr所指向的那一个地点
int* p = new int(10) 创建一个int类型的变量,存放10;<—> delete p
int* arr = new int[10] 创建一个10个整形数据长度的数组;<—>delete[] arr;

Notes:
1、指针a本质上也是局部变量,所以是放在栈区的。
2、指针保存的数据,放在堆区,堆区的特点是由程序员分配释放。

在这里插入图片描述
在这里插入图片描述


二、&引用

别名,就是小名,指的都是同一个人。
引用的本质在c++内部实现是一个指针常量.
int& ref = a自动转换为 int* const ref = &a;
指针的指向不变,这也说明了为什么引用的两个特点:
1、一旦初始化后,不能改方向。定义的时候必须给定是对谁取别名。
2、不可以再改方向,所有操作均视为赋值

#include<iostream>
using namespace std;
int& test0()
{
	//a是局部变量,放在栈中,由编译器自动分配释放
	int a = 10;
	return a;
}
int& test1()
{
	//a是静态变量,放在全局内存中,其特点是所有程序结束后由操作系统释放
	static int a = 10;
	return a;
}
int main() {

	int& ref = test0();//返回的是a的一个别名,用同样的数据类型接住
	cout << ref << endl;//编译器保留一次
	cout << ref << endl;//因为ref是a的一个别名,而a已经被释放了,所以乱码
	
	int& ref2 = test1();
	cout << ref2 << endl;
	cout << ref2 << endl;
	
	test1() = 100;
	//test1()作为a的别名可以当成左值。
	//被赋值,而ref2又是a的别名。
	cout << ref2 << endl;
	cout << ref2 << endl;
	return 0;
}

在这里插入图片描述

常量引用

一般用于修饰形参,防止误操作。
在最前面加个const 就代表约束了这个参数,只读不能改!
类似于const int * p约束指针
const int& p 本质上<——>const int * const p
p只读,不可改(大小、方向)。
在这里插入图片描述
实验:

#include<iostream>
using namespace std;

void test(const int *p)
{
	//a是静态变量,放在全局内存中,其特点是所有程序结束后由操作系统释放
	static int a = 10;
	cout << *p << endl;
	cout << p << endl;
	p = &a;
	cout << *p << endl;
	cout << p << endl;
}
int main() {
	
	int a = 1;
	int* p = &a;

	cout << *p << endl;
	cout << p << endl;
	cout << "*****before*****" << endl;
	test(p);
	cout << "*****after*****" << endl;
	cout << *p << endl;
	cout << p << endl;
	return 0;
}

在这里插入图片描述
结论:
函数的形参是在栈区内重开一个指针,和原来在main函数里面的指针一样指向某个变量。指针就是个地址。
值和地址的关系是一对多。多个指针指向同一个地址,有的时候要求函数内的指针是只读的,不能改变值,所以要在前面加const。
形参里面的指针方向具体怎么改不影响其他指针,方向对于每个指针来说是独立的,但是访问地址的值并修改,会影响大家,所以要约束一些指针的权限为只读

三、函数参数

1、参数
在C++中,函数的形参列表中的形参是可以有默认值的。

语法: 返回值类型 函数名 (参数= 默认值){}

如果某个位置参数有默认值,那么从这个位置往后,从左向右,必须都要有默认值
声明和实现中只能有一个有默认参数,otherwise对于编译器来说,具有二义性
二义性是函数调用的首要需要避免的问题。

int func2(int a, int b = 10, int c);//报错
//这是个函数声明用;结尾,好处是func2可以在任意地方写

2、重载
就是不同的参数会被认为是不同的函数,即便名字相同
以下视为不同的函数

void func()
{
	cout << "func 的调用!" << endl;
}
void func(int a)
{
	cout << "func (int a) 的调用!" << endl;
}

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

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

相关文章

运行时内存数据区之虚拟机栈——操作数栈

操作数栈 每一个独立的栈帧中除了包含局部变量表以外&#xff0c;还包含一个后进先出(Last-In-First-Out)的操作数栈&#xff0c;也可以称之为表达式栈(Expression Stack)。操作数栈&#xff0c;在方法执行过程中&#xff0c;根据字节码指令&#xff0c;往栈中写入数据或提取数…

Netty缓冲区ByteBuf源码解析

在网线传输中&#xff0c;字节是基本单位&#xff0c;NIO使用ByteBuffer作为Byte字节容器&#xff0c; 但是其使用过于复杂&#xff0c;因此Netty 写了一套Channel&#xff0c;代替了NIO的Channel &#xff0c;Netty 缓冲区又采用了一套ByteBuffer代替了NIO 的ByteBuffer &…

微服务+springcloud+springcloud alibaba学习笔记【OpenFeign的使用】(5/9)

OpenFeign的使用 5/91、OpenFeign简介1.1、Feign及OpenFeign概念和作用1.2、Feign和OpenFeign区别2、OpenFeign使用步骤2.1、创建Feign消费端微服务2.2、修改POM文件配置2.3、编写yml配置文件2.4、编写主启动类2.5、编写业务类2.5.1、编写 service 层接口&#xff0c;用于服务提…

什么是线性回归?线性回归有什么特征?

什么是线性回归 线性回归定义与公式 线性回归(Linear regression)是利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式。 特点&#xff1a;只有一个自变量的情况称为单变量回归&#xff0c;多于一个自变量情况的叫做多元回归 线…

Orange Pi 5B面世,传承经典,再续传奇

近日&#xff0c;香橙派又出大招。刚刚发布的Orange Pi 5B在性能和表现上再度升级。此前&#xff0c;Orange Pi 5凭借出色的性能和极低的价格被誉为“地表最高性价比开发板”&#xff0c;一经上市就引起市场轰动&#xff0c;销量引领同类产品市场&#xff0c;获得极佳口碑。那么…

【音视频第13天】另外一种拥塞控制算法-TransportCC

目录与Goog-REMB区别TrendLine滤波器与Goog-REMB区别 与Goog-REMB有两个区别&#xff1a; 将拥塞评估算法从接收端移动到了发送端&#xff0c;评估和控制是一体的。TransportCC是发送端评估发送端接着改变码率&#xff0c;REMB是接收端评估&#xff0c;把评估出来的值给发送端…

STL源码剖析-分配器 Allocator

分配器(Allocator) 分配器给容器用的&#xff0c;是一个幕后英雄的角色。分配器的效率非常重要。因为容器必然会使用到分配器来负责内存的分配&#xff0c;它的性能至关重要。 在C中&#xff0c;内存分配和操作通过new和delete完成。 new中包含两个操作&#xff0c;第一步是…

HTML5 Input 类型

文章目录HTML5 Input 类型Input 类型: colorInput 类型: dateInput 类型: datetimeInput 类型: datetime-localInput 类型: emailInput 类型: monthInput 类型: numberInput 类型: rangeInput 类型: searchInput 类型: telInput 类型: timeInput 类型: urlInput 类型: weekHTML…

手撕哈希表

&#x1f308;感谢阅读East-sunrise学习分享——[进阶数据结构]哈希表 博主水平有限&#xff0c;如有差错&#xff0c;欢迎斧正&#x1f64f;感谢有你 码字不易&#xff0c;若有收获&#xff0c;期待你的点赞关注&#x1f499;我们一起进步&#x1f680; &#x1f308;我们上一…

SNN demo

记录一个同门给的SNN demo&#xff0c;仅供自己参考 1 SNN和ANN代码的差别 SNN和ANN的深度学习demo还是差一些的&#xff0c;主要有下面几个&#xff1a; 输入差一个时间维度T&#xff0c;比如&#xff1a;在cv中&#xff0c;ANN的输入是&#xff1a;[B, C, W, H]&#xff0c…

Spring WebFlow-远程代码执行漏洞(CVE-2017-4971)

Spring WebFlow-远程代码执行漏洞&#xff08;CVE-2017-4971&#xff09; 0x00 前言 Spring WebFlow 是一个适用于开发基于流程的应用程序的框架&#xff08;如购物逻辑&#xff09;&#xff0c;可以将流程的定义和实现流程行为的类和视图分离开来。在其 2.4.x 版本中&#x…

浅说情绪控制被杏仁体劫持

2023年4月16号&#xff0c;没想到被杏仁体劫持那么严重&#xff0c;触发手抖和口干的症状&#xff0c;这个还真是自己万万没有想到的。 人生要修炼两条线&#xff1a;一条明线是做的事情&#xff0c;那是自己要做的具体事情。 一条暗线是修炼的自己&#xff0c;这次也做了测试…

云安全——Docker Daemon

0x00 前言 其他云安全相关内容&#xff0c;请参考&#xff1a;云安全知识整理 0x01 Docker Daemon Daemon是Docker的守护进程&#xff0c;Docker Client通过命令行与Docker Damon通信&#xff0c;完成Docker相关操作&#xff0c;2375端口是Daemon的未授权端口。 0x01 2375 …

设计模式之监听模式

本文将会介绍设计模式中的监听模式。   监听模式是一种一对多的关系&#xff0c;可以有任意个&#xff08;一个或多个&#xff09;观察者对象同时监听某一个对象。监听的对象叫观察者&#xff08;Observer&#xff09;&#xff0c;被监听的对象叫作被观察者&#xff08;Obser…

QObject对象生命周期管理

QObject对象生命周期管理 1.C中对象的生命周期管理是一个非常重要的话题&#xff0c;因为C需要程序员自己手动管理内存&#xff0c;而这也是C程序经常容易出现内存问题的重要原因。 1.1 特别是多线程环境下如何正确管理好对象的生命周期&#xff0c;更是C程序开发中的一个难点…

对抗样本-(CVPR 2022)-通过基于对象多样化输入来提高有针对性对抗样本的可迁移性

论文地址&#xff1a;https://arxiv.org/abs/2203.09123 代码地址&#xff1a;https://github.com/dreamflake/ODI 摘要&#xff1a;本文提出了一种新的方法来生成有针对性的对抗样本&#xff0c;该方法通过使用多种不同的输入图像来生成更加丰富和多样化的图像。具体而言&…

hashlib模块

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 hashlib模块专栏&#xff1a;《python从入门到实战》 哈希算法&#xff0c;也叫摘要算法。 加密&…

Postcat 插件上线,支持 ApiPost 格式导入

作为开源的 API 管理工具&#xff0c;Postcat 已经支持 Postman、swagger、Eolink 等平台的数据导入导出。 前不久有用户跟我们提需求&#xff0c;想要 Postcat 支持国内的一些主流的 API 管理工具&#xff0c;好消息是现在不就支持了么&#xff01; 最近我们的插件广场上线了一…

etcd概述

本文主要介绍了 etcd 相关概念&#xff0c;以及 etcd 的主要使用场景 1. 介绍 etcd 是云原生架构中的基础组件&#xff0c;由 CNCF 孵化托管。etcd 在微服务和 kubernetes 集群中不仅可以作为服务注册中心用于服务发现&#xff0c;还可以作为 key-value 存储中间件etcd 是 Co…

Spring的Bean初始化过程和生命周期

Spring的Bean初始化过程和生命周期一、Spring创建bean的流程图二、Spring创建bean的详细流程1.加载bean信息2.实例化bean3.bean属性填充4.初始化bean5.后置操作三、bean的生命周期四、总结Spring的核心功能有三点IOC、DI、AOP&#xff0c;IOC则是基础&#xff0c;也是Spring功能…