C++ 的内存区域主要分为以下五个部分:
-
程序代码区(Code Segment): 程序代码区用于存储程序的二进制代码,包括函数和方法。此内存区域是只读的,以防止程序意外修改自己的指令。
-
全局/静态存储区(Global/Static Storage): 全局/静态存储区用于存储全局变量、静态变量和常量(包括字符串常量)。这些变量在程序启动时分配内存,在程序结束时释放内存。全局/静态存储区的变量具有固定的内存地址。
-
栈(Stack): 栈是用于存储局部变量和函数调用所需的临时数据的内存区域。栈遵循后进先出(LIFO,Last In First Out)原则,即最后进入的数据最先被移除。栈内存分配和回收速度非常快,但空间有限。当栈空间不足时,可能会导致栈溢出错误。
-
堆(Heap): 堆是用于存储动态分配的内存块的内存区域。与栈不同,堆的空间较大,但分配和回收速度相对较慢。在C++中,可以使用
new
和delete
操作符在堆上分配和释放内存。为了避免内存泄漏,需要确保分配的内存在使用完毕后被正确释放。 -
自由存储区(Free Store): 自由存储区是C++标准中的术语,通常与堆互换使用。实际上,自由存储区是由C++的
new
和delete
操作符管理的内存区域。在大多数实现中,自由存储区和堆是同一内存区域。
在编写C++程序时,需要了解这些内存区域的特点,以便正确分配和管理内存。动态内存管理尤为重要,因为它容易导致内存泄漏和程序崩溃。C++11及以后的版本引入了智能指针,可以帮助程序员更容易地管理动态内存。
#include <iostream>
#include <memory>
// 全局变量(全局/静态存储区)
int global_var;
// 静态变量(全局/静态存储区)
static int static_var;
// 函数(程序代码区)
void func() {
std::cout << "这是一个函数,位于程序代码区。" << std::endl;
}
// 主函数(程序代码区)
int main() {
// 局部变量(栈)
int local_var;
// 字符串常量(全局/静态存储区)
const char* str = "Hello, World!";
// 动态内存分配(堆/自由存储区)
int* dynamic_var = new int;
// 智能指针(栈,但管理的内存位于堆/自由存储区)
std::unique_ptr<int> smart_ptr(new int);
// 输出不同内存区域的变量地址
std::cout << "程序代码区:" << std::endl;
std::cout << " func 地址:" << (void*)&func << std::endl;
std::cout << " main 地址:" << (void*)&main << std::endl;
std::cout << "全局/静态存储区:" << std::endl;
std::cout << " global_var 地址:" << &global_var << std::endl;
std::cout << " static_var 地址:" << &static_var << std::endl;
std::cout << " 字符串常量地址:" << (void*)str << std::endl;
std::cout << "栈:" << std::endl;
std::cout << " local_var 地址:" << &local_var << std::endl;
std::cout << " 智能指针地址:" << &smart_ptr << std::endl;
std::cout << "堆/自由存储区:" << std::endl;
std::cout << " dynamic_var 地址:" << dynamic_var << std::endl;
std::cout << " 智能指针管理的内存地址:" << smart_ptr.get() << std::endl;
// 释放动态内存
delete dynamic_var;
// 注意:智能指针在离开作用域时会自动释放内存,无需手动释放
return 0;
}