C++内存组织结构点滴

来源:互联网 发布:java 树形结构 编辑:程序博客网 时间:2024/05/17 04:02

1) 调用函数(包括main函数)时临时变量在栈中, 且向下生长; 动态分配的变量在堆中, 且向上生长;

2) 类成员变量的存放默认按最大的基本成员变量类型对齐(int, double等), 比如在成员变量中最大的为int类型, 则一个char类型占用一个字, 但是如果后面的变量为其他类型, 则会空出3个字节再存放其他的变量; 但是这个字对齐的方式可以通过编译选项来改变, 在VC里可以用 #pragma pack(n) 来设置, n就是对齐的字节大小; 从别的地方了解到:
在 #pragma pack(n)后一定不要include其他头文件,若包含的头文件中改变了align值将产生非预期结果。
VC中提供了一种安全使用pack的方法
#pragma pack( [ push | pop ], n )
#pragma pack( push, n)
将当前的align值压入编译器的一个内部堆栈并使用 ,n作为当前的align值,而#pragma pack(pop)则将内部堆栈中的栈顶值作为当前的align值,这样就保证了嵌套pack时的正确。

3) 有虚函数的类多了一个虚函数表的指针, 所以会多出4个字节. 一般放在对象的首部(也可能在尾部);

4) 无论是全局函数还是类函数, 其代码都在堆的代码段, 而全局数据在堆的数据段; 所有的同类的对象共享类函数, sizeof()函数取的大小是栈中变量占的内存大小, 所以不会包含有函数, 特殊情况是: 如果一个不带任何成员变量和成员函数的类, 其sizeof()值为1;

5) 静态变量(包括类的静态成员变量)在全局数据段;

6) 临时变量作用域结束时并不代表其生命周期结束, 因为生命周期是从函数开始到函数结束(入栈到出栈), 所以还会继续存在栈中, 知道该函数返回才会出栈;

7) 栈中尚未分配的空间的值是不确定的, 即使事先通过指针的方式修改了其中的值, 在正式分配这个空间后(不知道编译器初始化这个空间没有), 其值仍然是不确定的;

8) 题外讨论指针减法运算的问题: 只有同类型的指针可以做此运算, 若不同类型可以用reinterpret_cast<>来进行强制转换; 两个指针Type *p1, Type *p2减法后的值为 (p1-p2)/sizeof(Type), 也就是两个地址间可以存放多少个该类型的数据的个数, 这里要注意char类型的指针, 由于内存字对齐的关系, 得到的值一定是字长的倍数; 指针与整数的加减法运算遵循的原则是偏移多个sizeof(Type)的值, 所以p2 = p1+ n 得到的p2的值比p1大 n*sizeof(Type), 这里p2比p1大的数就可能不是字长的倍数了

9) 用 cout << 输出char类型变量的地址要用(void*)转换, 否则会被当作字符串指针, 输出的是一个未定义的字符串(无法预料在哪里结束); 顺便说一句: 输出指向NULL的char指针会发生运行时错误, 而输出指向NULL的其他类型的指针会是00000000, 其原因估计与前面相同.

10)c++ standard要求,在同一个access section中,members的排列只需符合“较晚出现的members在class object中有较高的地址”这一条件既可。也就是说,各个members并不一定得连续排列。什么东西可能会介于被声明的members之间 呢?members的边界调整可能就需要填补一些bytes。对于c和c++而言,这的确是真的,对当前的c++编译器实现情况而言,这也是真的。

原创粉丝点击