我一直觉得内存是很复杂的东西......也许我把这篇文章完成的时候,我会了解一点c++的内存管理机制
从硬件开始
内存器地址空间->总线地址空间->cpu地址空间->虚拟内存地址空间->程序地址空间(逻辑地址空间)
程序地址空间对c++程序员来说是可见的,其他地址空间我们并不关心
通过打印pointer的值 可以得到我们设立的变量和代码段在程序地址空间得分布情况
虚拟内存地址空间由操作系统管理,它把复杂的内存地址空间虚拟成一个平坦的 巨大的虚拟内存地址空间
在32位机上,这一空间大小是4GB
在c++程序中 内存空间被分为几个区域:
常量 栈 堆 自由存储 全局和静态
int main()
{
char * p1 = " hello " ;
char p2[ 10 ] = " hello " ;
char * p3 = " hello " ;
printf( " %d %d %d " ,p1,p2,p3);
getchar();
}
从这段代码可以看到 p1和p3地址相同(这不是一定的,取决于编译器优化,但现在的编译器几乎都是)它们跟p2相隔很远 其原因就是 字符串常量保存于常量区,常量区的值不能被修改。
但是const修饰符跟常量区无关。
exceptional c++还特别强调了一点:堆跟自由存储之间的关系。标准中堆是malloc realloc和free这样的c函数使用的内存 自由存储是new和delete使用的内存 标准没有规定他们是否相关联 唯一可以肯定的是 malloc 和free不会用new 和delete实现。
堆跟自由存储这样有些暧昧的联系确实令人难以理解,在我的认识中 new 和delete的语义更倾向于说明性 malloc和free更倾向于过程性(命令性),即new和delete只关心结果 malloc和free则明确规定了实现方式。相应地,自由存储和堆的语义也有类似的关系,一般来说 自由存储由堆来实现是很自然的。
栈是一个跟汇编语言中栈几乎重叠的概念,在c++中 栈负责函数参数传递和函数局部变量存储(包括main),所有函数共享一个栈,他们各自使用一个栈段。像在汇编中一样 栈内存不仅可以由push和pop操作,还能被随机访问。(除了栈顶指针寄存器之外,还有栈偏移指针寄存器)因此栈内存中的变量可以随意使用。
全局和静态变量空间 凡是static修饰的变量和函数都存储在这一空间中 全局变量也存储在这个空间中,其中还包括了全局函数和类的静态成员函数。
特别提出的是 类的非静态成员函数不在其中,类的非静态成员函数不允许取地址,也无法通过函数指针访问。甚至类型强制转换都被不允许。换句话说,类的成员函数就好像不在内存中一样。