MST

星途 面试题库

面试题:C++中栈内存和堆内存分配的主要区别

请阐述C++中栈内存分配和堆内存分配在分配方式、生命周期、内存管理等方面的主要区别,并分别举例说明在哪些场景下会使用栈内存分配,哪些场景会使用堆内存分配。
43.8万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

1. 分配方式

  • 栈内存分配:由编译器自动分配和释放,函数内定义的局部变量(非动态分配)都在栈上分配内存。例如:
void func() {
    int num = 10; // num 在栈上分配内存
}
  • 堆内存分配:需要程序员手动使用 new(C++)或 malloc(C兼容)等操作符来分配内存。例如:
int* ptr = new int(10); // 在堆上分配一个 int 类型的内存空间,并初始化为 10

2. 生命周期

  • 栈内存分配:其生命周期与所在函数或代码块紧密相关。当函数执行结束或代码块结束时,栈上的变量会自动被销毁,内存被释放。例如:
void func() {
    int num = 10; 
} // 函数结束,num 的内存被自动释放
  • 堆内存分配:其生命周期取决于程序员手动释放。使用 new 分配的内存,必须使用 delete 来释放;使用 malloc 分配的内存,必须使用 free 来释放。若不手动释放,会导致内存泄漏。例如:
int* ptr = new int(10); 
// 若之后没有 delete ptr; 则会发生内存泄漏

3. 内存管理

  • 栈内存分配:编译器自动管理,程序员无需手动干预内存的释放,不易出现内存泄漏问题。
  • 堆内存分配:程序员负责分配和释放内存。如果忘记释放,会造成内存泄漏;多次释放同一块内存会导致程序崩溃等问题。例如:
int* ptr = new int(10); 
delete ptr; 
delete ptr; // 第二次释放会导致未定义行为

4. 适用场景

  • 栈内存分配场景
    • 当变量的生命周期与函数执行周期相同,且占用空间较小,例如函数内的临时变量、循环变量等。比如:
void calculateSum() {
    int sum = 0; 
    for(int i = 0; i < 10; ++i) {
        sum += i;
    }
    // sum 和 i 都在栈上分配,函数结束自动释放
}
- 当需要快速分配和释放内存,因为栈的操作效率较高。例如频繁调用的函数内的局部变量。
  • 堆内存分配场景
    • 当需要动态分配内存,且内存大小在编译时无法确定。例如,根据用户输入创建数组:
int size;
std::cin >> size;
int* arr = new int[size]; 
// 这里数组大小在运行时由用户输入决定,只能在堆上分配
- 当对象的生命周期需要跨越多个函数调用或代码块,需要手动控制其生命周期时。例如,在一个函数中创建对象,在另一个函数中使用并最终释放:
class MyClass {
public:
    MyClass() { std::cout << "Constructor" << std::endl; }
    ~MyClass() { std::cout << "Destructor" << std::endl; }
};

MyClass* createObject() {
    return new MyClass();
}

void useObject(MyClass* obj) {
    // 使用 obj
}

void releaseObject(MyClass* obj) {
    delete obj;
}

int main() {
    MyClass* obj = createObject();
    useObject(obj);
    releaseObject(obj);
    return 0;
}