栈上创建和堆上创建区别
目录
区别
1.释放方式
2.内存大小方式
3.分配效率
4.生命周期
5.访问方式
总结
被朋友发现我学C++了,可恶的奥子,想吃鱼了
int a[10]; //这种就是栈上创建
int *a = new int[10]; //这种就是堆上创建
区别
1.释放方式
栈上创建:
内存由编译器自动分配(进入作用域时)和释放(离开作用域时),无需手动干预。
堆上创建:
通过new
关键字手动申请内存 如Student* p = new Student()
,必须通过delete
(或delete[]
用于数组)手动释放,否则会导致内存泄漏。堆创建一般都是指针来接收new或者malloc创建对象
void func() {int a; // 栈上分配,函数结束时自动释放Student s; // 栈上创建对象,函数结束时自动调用析构函数
}
void func() {int* p = new int; // 堆上分配delete p; // 必须手动释放,否则内存泄漏Student* s = new Student();delete s; // 释放时会自动调用对象的析构函数
}
2.内存大小方式
栈内存:
大小固定(通常几 MB,由编译器 / 系统决定),如果分配过大的内存(如超大数组),会导致 栈溢出(stack overflow)错误。int arr[1000000]; // 可能栈溢出(数组过大)
堆内存:
大小灵活(理论上可接近系统可用内存,通常几 GB),适合需要大量内存的场景(如动态数组、大型对象)。int* arr = new int[1000000]; // 堆上分配,不易溢出(只要系统有足够内存)
delete[] arr;
3.分配效率
栈上分配:
效率极高,通过调整栈指针(stack pointer)完成,几乎没有额外开销(类似 “移动指针” 的操作)。
堆上分配:
效率较低,需要操作系统在堆内存中查找可用的连续空间,还要维护内存分配表(记录已分配 / 空闲区域),频繁的 new/delete 可能导致内存碎片。
4.生命周期
栈上对象:
生命周期与作用域绑定,离开作用域后立即销毁(如函数返回、代码块结束),无法在作用域外使用。堆上对象:
生命周期由程序员控制,只要不调用delete
,即使创建它的作用域结束,对象依然存在,可通过指针在其他地方访问。
Student* getStudent() {Student s; // 栈上对象return &s; // 错误!返回后 s 已销毁,指针变为“野指针”
}
Student* getStudent() {return new Student(); // 堆上对象,返回后仍可使用
}// 使用时:
Student* p = getStudent();
// ... 使用 p ...
delete p; // 不再需要时手动释放
5.访问方式
栈上对象:
直接通过变量名访问(如 s.age),无需指针间接操作。
堆上对象:
必须通过指针访问(如 p->age),指针本身通常在栈上存储,指向堆内存中的对象。
总结
栈上创建由编译器自动自动分配释放、内存有限、效率高、生命周期与作用域绑定,堆上创建需手动new/delete、内存灵活、效率较低、生命周期由程序员控制。