当前位置: 首页 > news >正文

c++ 堆栈内存、引用和指针 - 学习总结

c++ 堆栈内存、引用和指针

  • 一、堆和栈内存
    • 1.1、内存地址
    • 1.2、内存布局
  • 二、指针 - 管理变量地址的工具
    • 2.1、指针基本总结
    • 2.2、指针的价值
  • 三、引用
  • 四、引用和指针的关系

一、堆和栈内存

在学习引用和指针之前,先要了解堆和栈内存的相关概念。

1.1、内存地址

一个打印内存地址的示例:(先声明变量,再用 & 获取地址)

#include <iostream>
using namespace std;
int main () {
int int_value = 1;
double double_value = 0.0;
char array_value[10];
cout << "address of int_value: " << &int_value << endl;
cout << "address of double_value: " << &double_value << endl;
cout << "address of array_value: " << &array_value << endl;
cout << "array_value[1]:" << &array_value + 1 << endl;
return 0;
}

代码解析:

  1. 每一个变量都有一个内存位置,内存地址表示这个位置;
  2. "&"符号可以获取变量地址
  3. &array_value + 1 不是值 +1,而是位置再 +1(下一个字节)
  4. &array_value 取的是 array_value[0] 的地址
  5. 代码中获取的都是栈内存(没用 new 和 delete)
  6. 上面每次运行的结果都不一定相同,因为地址是操作系统分配的。

1.2、内存布局

电脑可以有多个进程,这是其中一个进程的内存布局图。

可以看到 有两个重点
static memory layout:存放全局或者静态数据
dynamic memory layout:程序使用的内存-> stack (栈内存)+ heap(堆内存)
在这里插入图片描述
堆栈内存的对比:

在这里插入图片描述
使用场景举例:

在这里插入图片描述
1、一些实时的变量,一般就会在栈内存中。因为不超过几十MB

2、如果是体积很大的数据(点云或者图像),就需要在堆内存申请。

堆内存
堆内存用关键字new来创建,用关键字delete来释放
需要用栈内存上的一个变量(指针)来表示地址,来指向堆内存的位置并对堆内存上的对象进行管理

二、指针 - 管理变量地址的工具

2.1、指针基本总结

定义:指针(pointer)是一种特殊的变量,其值为内存地址。

作用:通过指针可以直接访问和操作内存中的数据。

声明语法:Type *pointer_ame;,其中Type是指针所指向的数据类型,pointer_pame是指针变量名。

初始化:可以将指针初始化为某个变量的地址,也可以将其初始化为nullptr(空指针)。

取地址操作符:&,用于获取变量的地址。

解引用操作符:*,用于访问指针所指向的数据。

长度:不管 Type 是什么,指针长度都是一样,都是一个代表内存地址的长的十六进制数。

示例代码:

#include <iostream>
using namespace std;
int main () {int var = 20; // 实际变量的声明
int *ip; // 指针变量的声明
ip = &var; // 在指针变量中存储 var 的地址
cout << "Value of var variable: ";
cout << var << endl; // 输出在指针变量中存储的地址
cout << "Address stored in ip variable: ";
cout << ip << endl; // 访问指针中地址的值
cout << "Value of *ip variable: ";
cout << *ip << endl;return 0;
}

2.2、指针的价值

在 C++ 中,指针的存在是为了提供更灵活的变量操作和内存管理方式:

  1. 内存访问和操作:指针允许程序直接访问和操作内存地址。这对于底层编程(如操作系统或嵌入式
    系统开发)非常重要,因为它们需要精确控制内存和硬件。
  2. 效率提升:通过指针,函数可以直接操作原始数据而不是其副本,这样可以避免不必要的数据复制
    特别是对大型数据对象,可以显著提高程序的效率。
  3. 动态内存分配:指针是动态内存分配的基础。
  4. 实现数据结构:指针对于实现各种数据结构(如链表、树、图等)是必不可少的。
  5. 多态和接口:在面向对象编程中,通过基类指针或引用,可以访问派生类的对象,实现多态行为。
  6. 批量传递:C++函数默认只能返回一个值。通过使用指针,函数可以修改传入的变量,从而实现返
    回多个值的效果。

三、引用

概念:

引用(reference)是一个别名,它提供了对已存在变量的另一个名称。

• 声明语法:type& refName = var;,其中type是引用所引用的类型,refName是引用的名称,var是被引用的变量。

• 作用:ref 就是 y 的引用,意味着 ref 和 y 引用了相同的内存地址对其中一个的修改会影响到另一个

比如下面的例子, a 和 b 的地址完全一样。

int a = 111;
int& b = a;
cout << "b"<< b << endl;
cout << "address"<< &a <<" "<< &b << endl;

特性:

• 一旦初始化,不能重新绑定:引用一旦与某个变量绑定,就不能再改变其指向的变量。
•不占用额外内存:引用不占用额外的内存空间,它只是变量的一个别名。
•引用作为函数参数:引用可以作为函数的参数,通过引用参数可以直接修改函数外部的变量。

应用场景:

• 函数返回值:函数可以返回引用类型,使得可以返回函数内部的局部变量或临时对象。
•函数参数传递:通过引用参数可以避免函数参数的拷贝,提高程序的效率。
•函数返回值赋值:可以将函数返回的引用直接赋值给其他变量,提高代码的简洁性和可读性。

四、引用和指针的关系

• 指针可以为空(nullptr);但引用不能,在定义时必须绑定一个变量。

• 指针和引用都是C++中非常有用的工具,但需要根据具体情况选择使用哪种。在大多数情况下,引用更
安全、更易读,而指针则更灵活、更强大。

• 引用实际上就是用指针实现的:编译器将引用转换为对应的指针操作,并在编译过程中进行优化和替
换。这样做的目的是为了让引用在语法上与指针有所区别,同时在底层实现上与指针相近,以保证引
用的高效性和易用性。

几乎只有C/C++提供最直接的内存管理机制:指针,而其他语言不会让用户直接用指针管理、操作内存。

• 指针(包括引用)的优势在于提供了直接内存访问、动态内存分配、高效数据传递、与硬件直接交互
的优势,但它也带来了内存错误、复杂性和安全性等挑战。

相关文章:

  • 网络时间同步设备(时间同步系统)操作及应用方案
  • 用静态工厂方法代替构造器
  • 11.子串简写
  • 【行业颠覆者】桔数安康签约首发,开创养老服务新篇章!
  • 数字化接口、网络身份证实名认证接口、C#实名认证接口说明示例
  • 微服务篇-C 深入理解第一代微服务(SpringCloud)_VII 深入理解Swagger接口文档可视化管理工具
  • 蓝桥杯算法基础(32):素数,埃式筛法,快速幂,斐波那契与矩阵幂运算
  • 【项目技术介绍篇】若依开源项目RuoYi-Cloud后端技术介绍
  • 前端开发学习笔记(1)
  • 音频RK809
  • (C语言)fgets与fputs函数详解
  • Phoenix伪分布安装
  • 剑指Offer题目笔记21(计数排序)
  • 【Win】使用PowerShell和Webhooks轻松发送消息至Microsoft Teams
  • 【Java常用的API】JDK8相关时间类
  • 30天自制操作系统-2
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • echarts花样作死的坑
  • JS实现简单的MVC模式开发小游戏
  • Laravel Mix运行时关于es2015报错解决方案
  • Python - 闭包Closure
  • React系列之 Redux 架构模式
  • 程序员最讨厌的9句话,你可有补充?
  • 目录与文件属性:编写ls
  • 手机端车牌号码键盘的vue组件
  • 首页查询功能的一次实现过程
  • 我从编程教室毕业
  • 7行Python代码的人脸识别
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • (1)(1.11) SiK Radio v2(一)
  • (Python第六天)文件处理
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (Ruby)Ubuntu12.04安装Rails环境
  • (附源码)计算机毕业设计大学生兼职系统
  • (简单) HDU 2612 Find a way,BFS。
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (算法)前K大的和
  • (转)编辑寄语:因为爱心,所以美丽
  • (最简单,详细,直接上手)uniapp/vue中英文多语言切换
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**
  • . ./ bash dash source 这五种执行shell脚本方式 区别
  • .mysql secret在哪_MYSQL基本操作(上)
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料
  • .Net 应用中使用dot trace进行性能诊断
  • .net 中viewstate的原理和使用
  • .NET:自动将请求参数绑定到ASPX、ASHX和MVC(菜鸟必看)
  • .NET是什么
  • // an array of int
  • :“Failed to access IIS metabase”解决方法
  • @Controller和@RestController的区别?
  • @Responsebody与@RequestBody
  • @staticmethod和@classmethod的作用与区别
  • @synthesize和@dynamic分别有什么作用?