内存,也就是我们常说的内存条,是计算机系统中至关重要的组成部分,它不仅用于存储程序的代码和数据,还负责数据的快速访问和处理。计算机内部以字节为单位存储信息。当我们在程序中声明某种类型的变量时,实际上是在向系统申请一定数量的内存空间(以字节为单位)来存储数据。在本质上,所有与程序相关的内容都是关于内存中信息的表示和管理。

在程序运行时,内存被划分为不同的区域,每个区域有其特定的用途和管理方式。以下是C++程序中常见的内存分区及其详细介绍:

代码区(Code Segment)

代码区,也称为 .text 段,是存储程序的执行代码的区域。这个区域是只读的,以防止程序在运行过程中被意外修改。例如,编译后的 main 函数的逻辑存放在代码区。代码区还可能包含一些只读的常量,例如字符串字面量。

1
2
3
4
5
#include <iostream>
int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}

全局/静态存储区(Global/Static Storage)

全局变量和静态变量存放在全局/静态存储区。C++ 中,全局变量和静态变量通常存放在同一块内存区,不再区分初始化的和未初始化的部分。而在 C 语言中,全局变量被分为 .data 段(初始化)和 .bss 段(未初始化),但在 C++ 中,它们共同占用全局/静态存储区。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <iostream>
int globalVar = 0; // 全局变量
void function() {
    static int staticVar = 0; // 静态变量
    staticVar++;
    std::cout << staticVar << std::endl;
}
int main() {
    function();
    function();
    return 0;
}

栈区(Stack)

栈区用于存储函数调用时的局部变量、函数参数以及返回地址。栈区的内存分配和释放由编译器自动管理,遵循后进先出(LIFO)原则。当函数调用完成后,分配给该函数的栈空间会被释放。

1
2
3
4
5
6
7
8
9
#include <iostream>
void function(int a, int b) {
    int localVar = a + b;
    std::cout << localVar << std::endl;
}
int main() {
    function(3, 4);
    return 0;
}

在上面的例子中,ablocalVar 都是局部变量,存放在栈区。函数调用结束后,栈区中对应的内存空间会被回收。

堆区(Heap)

堆区用于动态内存分配。当使用 new(在C++中)或者 malloc(在C中)分配内存时,这些内存块会位于堆区。与栈区不同,堆区的内存分配和释放需要程序员手动管理,否则可能导致内存泄漏。

1
2
3
4
5
6
7
#include <iostream>
int main() {
    int* dynamicArray = new int[10]; // 动态分配内存
    // 使用动态数组...
    delete[] dynamicArray; // 释放内存
    return 0;
}

常量区(Constant Storage)

常量区用于存储编译时确定的常量数据,例如字符串字面量和其他常量。这些数据通常是只读的,以确保它们在程序运行过程中不会被修改。

1
2
3
4
5
#include <iostream>
int main() {
    char* c = "abc";  // "abc" 在常量区,c 在栈上。
    return 0;
}