C++学习 --内存四区

2023-11-02 01:36
文章标签 c++ 学习 内存 四区

本文主要是介绍C++学习 --内存四区,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1, 内存四区

1-1, 代码区

1-1-2, 特点

1-2, 全局区

1-2-1, 全局变量

1-2-2, 静态变量

1-2-3, 全局常量

1-3, 栈区

1-4, 堆区

1-4-1, new单个对象

1-4-2, delete单个对象

1-4-3, new&delete数组


1, 内存四区

四区中的数据,具有不同生命周期

1-1, 代码区

代码区存放的是编译后的C++代码二进制文件

1-1-2, 特点

特点共享、只读, 共享是只内存中的该段二进制文件可以反复执行,只读是指存放后的二进制文件不能被修改

1-2, 全局区

全局区存放的是C++代码的全局变量, 静态变量, 全局常量, 字符串常量的地方, 程序结束后由操作系统释放

1-2-1, 全局变量

全局变量为在函数外定义的变量

#include <iostream>
#include <string>using namespace std;/*全局变量存放在全局区,程序运行结束后由操作系统释放*///定义全局变量
int global_a = 10;
int global_b = 10;int main()
{int local_a = 10;int local_b = 20;cout << "局部变量的地址local_a:" << &local_a <<endl;cout << "局部变量的地址local_b:" << &local_b <<endl;cout << "全局变量的地址global_a:" << &global_a << endl;cout << "全局变量的地址global_b:" << &global_b << endl;system("pause");return 0;
}------------------------------------------------------------------
输出结果:
局部变量的地址local_a:00000045BEB5F9E4
局部变量的地址local_b:00000045BEB5FA04
//可以看出全局变量的地址与局部变量的地址不在一片内存空间
全局变量的地址global_a:00007FF74F00D000
全局变量的地址global_b:00007FF74F00D004

1-2-2, 静态变量

通过static 数据类型  变量名方式定义的变量为静态变量

#include <iostream>
#include <string>using namespace std;/*静态变量存放在全局区,程序运行结束后由操作系统释放*/int global_a = 10;
int global_b = 10;int main()
{//定义静态变量static int local_static_a = 10;static int local_static_b = 20;cout << "全局变量的地址global_a:" << & global_a << endl;cout << "全局变量的地址global_b:" << &global_b << endl;cout << "静态变量的地址local_static_a:" << &local_static_a << endl;cout << "静态变量的地址local_static_b:" << &local_static_b << endl;system("pause");return 0;
}
-----------------------------------------------------
输出结果:
//可以看出全局和静态变量存放在同一块内存区中
全局变量的地址global_a:00007FF60391D074
全局变量的地址global_b:00007FF60391D078
静态变量的地址local_static_a:00007FF60391D07C
静态变量的地址local_static_b:00007FF60391D080

1-2-3, 全局常量

在函数体外通过const 数据类型 变量名, 可定义一个全局常量

#include <iostream>
#include <string>using namespace std;/*全局常量,字符串常量存放在全局区,程序运行结束后由操作系统释放*/int global_a = 10;
int global_b = 10;//定义全局常量
const int c_global_a = 10;
const int c_global_b = 10;int main()
{//定义局部常量const int local_a = 10;const int local_b = 20;cout << "全局变量的地址global_a:" << & global_a << endl;cout << "全局变量的地址global_b:" << &global_b << endl;cout << "全局常量的地址c_global_c:" << &c_global_a << endl;cout << "全局常量的地址c_global_d:" << &c_global_b << endl;//&"aaaaa"表示获取该字符串常量的地址cout << "字符串常量的地址:" << &"aaaaa" << endl;cout << "局部常量的地址:" << &local_a << endl;cout << "局部常量的地址:" << &local_b << endl;system("pause");return 0;
}
----------------------------------------------------------------
输出结果:
//可以看出, 全局变量, 全局常量在同一块内存空间
全局变量的地址global_a:00007FF60F63D074
全局变量的地址global_b:00007FF60F63D078
全局常量的地址c_global_c:00007FF60F63ABB0
全局常量的地址c_global_d:00007FF60F63ABB4
字符串常量的地址:00007FF60F63ACA8
//可以看出局部常量与上面的常量不在一块内存空间
局部常量的地址:0000004A3B11F634
局部常量的地址:0000004A3B11F654

1-3, 栈区

栈区存放的是C++代码的函数的参数, 局部变量, 由编译器自动分配和释放。

注意:不要放回局部变量的地址, 因为局部变量在函数调用完后, 就被编译器释放。 

#include <iostream>
#include <string>using namespace std;/*局部变量和形参都是存放在栈区,由编译器分配和释放*/
int * func(int b)
{int a = 10;return &a;
}int main()
{int* p = func();cout << "调用func:" << *p << endl;system("pause");return 0;
}
---------------------------------------------------
输出结果:
//因为局部变量调用完后, 就被释放了, 所以这里没有获取到局部变量a的值
//同理形参b也一样
第一次调用func:-858993460

1-4, 堆区

堆区是由程序员分配和释放的, 若程序员不主动释放,在程序结束后由操作系统释放

1-4-1, new单个对象

通过new 数据类型(对象), 可在堆区创建一个地址,对象为地址指向的值, 返回指定数据类型的指针

#include <iostream>
#include <string>using namespace std;/*堆区的数据是由程序员分配的,若不主动释放,在程序
运行完成后, 由操作系统释放*/int * func()
{//通过new方式在堆区创建一块地址,返回对应数据类型的指针//地址存的数据是10//局部变量p,任然在栈区int* p = new int(10);return p;
}int main()
{int* p = func();cout << "调用func:" << *p << endl;cout << "调用func:" << *p << endl;system("pause");return 0;
}
-----------------------------------------------------
//能打印出10, 是因为10是存放在堆区上, 不会因为func调用完成后而释放
调用func:10
调用func:10

1-4-2, delete单个对象

通过delete 指针可手动释放堆区指定的内存空间

#include <iostream>
#include <string>using namespace std;/*堆区的数据是由程序员分配的,若不主动释放,在程序
运行完成后, 由操作系统释放*/int * func()
{//通过new方式在堆区创建一块地址,地址存的数据是10//局部变量p,任然在栈区int* p = new int(1011);return p;
}int main()
{int* p = func();cout << "调用func:" << *p << endl;//通过delete手动释放堆区的地址delete p;//该行调用,会报错,因为p指向的值已经被释放cout << "调用func:" << *p << endl;system("pause");return 0;
}
-----------------------------------------------------------
输出结果:
调用func:1011
//这里没有输出的因为是因为p已经被手动释放
调用func:

1-4-3, new&delete数组

通过new 数据类型[长度], 可在堆区创建一块数组地址空间, 同delete[] 指针, 手动释放创建的地址空间

#include <iostream>
#include <string>using namespace std;int * func()
{//表示在堆区中创建一个大小为10数组地址空间, 并赋值给指针arrint* arr = new int[10];//数组赋值for (int i = 0; i < 10; i++){arr[i] = i;}return arr;
}int main()
{int* arr = func();//逐个打印数组元素for (int i = 0; i < 10; i++){cout << arr[i] << " ";}cout << endl;//delete[]表示释放的是一个数组地址空间delete[] arr;system("pause");return 0;
}
-------------------------------------------------------------------
输出结果:
0 1 2 3 4 5 6 7 8 9

这篇关于C++学习 --内存四区的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/327196

相关文章

C++右移运算符的一个小坑及解决

《C++右移运算符的一个小坑及解决》文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数... 目录我遇到了这么一个www.chinasem.cn函数由此可以看到也很好理解总结我遇到了这么一个函数template<typename T>unsigned

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Python内存优化的实战技巧分享

《Python内存优化的实战技巧分享》Python作为一门解释型语言,虽然在开发效率上有着显著优势,但在执行效率方面往往被诟病,然而,通过合理的内存优化策略,我们可以让Python程序的运行速度提升3... 目录前言python内存管理机制引用计数机制垃圾回收机制内存泄漏的常见原因1. 循环引用2. 全局变

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

C++ STL-string类底层实现过程

《C++STL-string类底层实现过程》本文实现了一个简易的string类,涵盖动态数组存储、深拷贝机制、迭代器支持、容量调整、字符串修改、运算符重载等功能,模拟标准string核心特性,重点强... 目录实现框架一、默认成员函数1.默认构造函数2.构造函数3.拷贝构造函数(重点)4.赋值运算符重载函数

C++ vector越界问题的完整解决方案

《C++vector越界问题的完整解决方案》在C++开发中,std::vector作为最常用的动态数组容器,其便捷性与性能优势使其成为处理可变长度数据的首选,然而,数组越界访问始终是威胁程序稳定性的... 目录引言一、vector越界的底层原理与危害1.1 越界访问的本质原因1.2 越界访问的实际危害二、基

Python学习笔记之getattr和hasattr用法示例详解

《Python学习笔记之getattr和hasattr用法示例详解》在Python中,hasattr()、getattr()和setattr()是一组内置函数,用于对对象的属性进行操作和查询,这篇文章... 目录1.getattr用法详解1.1 基本作用1.2 示例1.3 原理2.hasattr用法详解2.

c++日志库log4cplus快速入门小结

《c++日志库log4cplus快速入门小结》文章浏览阅读1.1w次,点赞9次,收藏44次。本文介绍Log4cplus,一种适用于C++的线程安全日志记录API,提供灵活的日志管理和配置控制。文章涵盖... 目录简介日志等级配置文件使用关于初始化使用示例总结参考资料简介log4j 用于Java,log4c