A a(1); // 栈中分配
A b = A(1); // 栈中分配
A* c = new A(1); // 堆中分配
第一种与第二种没有区别,都是在进程虚拟地址空间中的栈中分配内存,而第三种使用 new 则在堆中分配内存。
栈中分配的内存,分配与释放由系统管理;堆中分配的内存,申请与释放由程序员手动管理。
堆与栈的对比:
- 堆和栈最大可分配的内存的大小
- 堆和栈的内存管理方式
- 堆和栈的分配效率
- 一般来说,对一个进程,栈的大小远远小于堆。栈以 M 为单位,堆以 G 为单位。
- 栈是系统数据结构,对于进程/线程是唯一的,它的分配与释放由操作系统来维护,不需要开发者来管理。
在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时,这些存储单元会被自动释放。
堆上的内存分配,亦称动态内存分配。程序在运行的期间用malloc申请的内存,这部分内存由程序员自己负责管理,其生存期由开发者决定:在何时分配,分配多少,并在何时用free来释放该内存。 - 栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率 比较高。
堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会 分 到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。
set<A> temp;
func(temp);
void func(set<A> &a)
{
A m();
A n();
a.insert(m);
a.insert(n);
}
分析:函数中 m,n 为临时变量,函数退出时会销毁。但 a 是 set<A> 引用类型的变量,故会将 m 与 n 的内容复制一份放到 temp 的存储空间。
若将 & 改为 ,则函数内写为 (a).insert(m); 即可。
set<A *> temp;
func(temp);
void func(set<A *> &a)
{
A *m = new A();
A *n = new A();
a.insert(m);
a.insert(n);
}
分析:需要手工 delete temp 中的 m 和 n。
set<A> temp;
func(temp);
void func(set<A> &a)
{
A *m = new A();
A *n = new A();
a.insert(*m); // 复制一份 m 的内容
a.insert(*n); // 复制一份 n 的内容
delete m;
delete n;
}
网友评论