MST
星途 面试题库

面试题:C++中堆和栈在内存分配上的差异及使用场景举例

请阐述C++中堆和栈在内存分配机制上有哪些不同,并分别举例说明在什么场景下会优先选择使用堆分配内存,什么场景下会优先选择栈分配内存。
19.9万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

堆和栈在内存分配机制上的不同

  1. 分配方式
    • :由编译器自动分配和释放,函数内局部变量的分配即在栈上。例如在函数void func() { int a = 10; }中,变量a的内存由编译器在栈上自动分配,函数结束时自动释放。
    • :需要程序员手动分配和释放,使用new(C++)或malloc(C语言)分配,delete(C++)或free(C语言)释放。如int* ptr = new int(20);,通过new在堆上分配内存,后续需delete ptr;来释放。
  2. 内存生长方向
    • :内存由高地址向低地址生长。在函数调用过程中,参数和局部变量依次入栈,栈顶指针向低地址移动。
    • :内存由低地址向高地址生长。当使用newmalloc分配内存时,从堆的起始地址开始,向高地址方向寻找足够大小的空闲空间。
  3. 空间大小
    • :空间大小通常较小,一般在几MB左右,不同操作系统和编译器可能有所不同。因为栈空间有限,递归函数如果没有正确的终止条件,很容易导致栈溢出。
    • :空间相对较大,理论上可使用的内存为系统剩余可用内存。
  4. 分配效率
    • :分配效率高,因为是由编译器自动管理,分配和释放过程简单快速。
    • :分配效率相对较低,由于堆的分配需要在堆内存空间中寻找合适的空闲块,并且可能涉及到内存碎片整理等操作。

优先选择堆分配内存的场景

  1. 动态内存需求:当程序运行时才知道需要多少内存,例如实现一个动态数组类,在初始化时不知道数组的最终大小,此时需要在堆上分配内存。
class DynamicArray {
private:
    int* data;
    int size;
public:
    DynamicArray(int initialSize) {
        size = initialSize;
        data = new int[size];
    }
    ~DynamicArray() {
        delete[] data;
    }
};
  1. 对象生命周期长:当对象需要在函数调用结束后仍然存在时,如全局对象或需要在不同函数间共享的对象,需在堆上分配。
class SharedObject {
    //...
};
SharedObject* globalObj = new SharedObject();

优先选择栈分配内存的场景

  1. 局部变量:函数内部使用的临时变量,其生命周期只在函数内部,如简单的循环计数器。
void loop() {
    int i;
    for (i = 0; i < 10; ++i) {
        //...
    }
}
  1. 性能敏感:对于一些对性能要求极高且内存需求较小的场景,栈分配由于其高效性是更好的选择。例如在频繁调用的函数中使用的小型临时对象。
void frequentlyCalledFunction() {
    struct SmallStruct {
        int a;
        char b;
    } temp;
    // 使用temp进行一些操作
}