c++堆与栈的简单认识
- 堆: 操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删 除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样代码 中的delete语句才能正确的释放本内存空间。我们常说的内存泄露,最常见的就是堆泄露(还有资源泄露),它是指程序在运行中出现泄露,如果程序被关闭掉的话,操作系统会帮助释放泄露的内存。
栈:在函数调用时第一个进栈的主函数中的下一条指令(函数调用语句的下一条可执行语句)的地址然后是函数 的各个参数,在大多数的C编译器中,参数是由右往左入栈,然后是函数中的局部变量。(参考课本)
1 #include <iostream> 2 3 int main(void) 4 { 5 using namespace std; 6 double * a = new double(5); 7 int b = 1; 8 cout << *a << endl; 9 cout << a << endl; 10 cout << &b << endl; 11 12 delete a; 13 return 0; 14 } 15 16 /*********************************** 17 * 5 18 * 0x1002c20 ----->heap(堆) 19 * 0x7ffe7bd82ec4 ----->stack(栈) 20 * *********************************/ 21 ~
堆和栈地地址格式不一样。说明它们在内存中地位置不一样。
-
一个由c/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区—存放函数体的二进制代码。(复制来自:http://www.cnblogs.com/likwo/archive/2010/12/20/1911026.html)
-
char a[] = "I like comouter!"; //I like conputer 时运行时分配的。意味着程序每次运行存储该字符串的地址都不一样。
char *b = "I like computer!" // I like conouter 是编译时就分配的。意味着一旦程序生成可执行代码,每次编译该字符串的地址都不再发生改变。1 #include <iostream> 2 3 int main(void) 4 { 5 using namespace std; 6 7 char a[] = "I like comouter!"; 8 char *b = "I like conputer!"; 9 10 cout << (void *)a << endl; 11 cout << (void *)b << endl; 12 13 return 0; 14 } 15 16 /************************************* 17 * [root@Busui cc]#c++ s./string 18 * 0x7ffe4868c8e0 19 * 0x400991 20 * [root@Busui cc]#c++ s./string 21 * 0x7ffdd6c640e0 22 * 0x400991 23 * [root@Busui cc]#./string 24 * 0x7fffaffc7ce0 25 * 0x400991 26 * [root@Busui cc]# 27 * ***********************************/
以下是别人博客复制来的,博客地址上面已给出:
2.6存取效率的比较
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在运行时刻赋值的;
而bbbbbbbbbbb是在编译时就确定的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。
比如:
#i nclude
void main()
{
char a = 1;
char c[] = "1234567890";
char *p ="1234567890";
a = c[1];
a = p[1];
return;
}
对应的汇编代码
10: a = c[1];
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]
0040106A 88 4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov al,byte ptr [edx+1]
00401073 88 45 FC mov byte ptr [ebp-4],al
第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。