1.堆栈的使用
栈
在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆
堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储 的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小 受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。
在C/C++中,内存一般分为,堆区,栈区,全局区,文字长量区,程序代码区!在函数中定义的局部变量是存在在栈区(除static局部变量,他是存在在全局区),动态生成的变量存在在堆区,由指针进行读写!全局变量,静态全局变量,静态局部变量是存放在全局区的! 堆是程序员进行申请和释放的,因此堆是向上,也就是向高地址方向的!栈是系统进行释放的,且栈区大小一般是定的2M,因此栈是向下,也就是向底地址方向!
全局未初始化读写数据段(BSS)
未初始化读写据是在程序中声明,但是没有初始化的变量,这些变量在程序运行之前不需要占用存储器的空间。静态未初始化变量也在这儿。
全局已初始化读写数据段(RW data)
已初始化数据是在程序中声明,并且具有初值的变量,这些变量需要占用存储器的空间,在程序执行时它们需要位于可读写的内存区域内,并具有初值,以供程序运行时读写。静态已初始化变量也在这儿。
只读数据段(RO data)
只读数据段是程序使用的一些不会被更改的数据,使用这些数方式类似查表式的操作,由于这些变量不需要更改,因此只需要放置在只读存储器中即可。常量字符串就是放在这里。
代码区
存放函数体的二进制代码。例:char *c=”hello world”
2.类中各种数据成员的初始化
const static
const static数据成员可以在类内初始化 也可以在类外,不能在构造函数中初始化,也不能在构造函数的初始化列表中初始化
static
static数据成员只能在类外,即类的实现文件中初始化,也不能在构造函数中初始化,不能在构造函数的初始化列表中初始化;
const
const数据成员只能在构造函数的初始化列表中初始化;
普通成员
普通数据成员不能在类内初始化,可以在构造函数中初始化,也可以在构造函数的初始化列表中初始化;
3.逻辑操作符
&&具有短路特性,即只要&&前的表达式为false后,&&后的表达式将不会再做判断。
||和&&不是左右顺序的,而是&&的优先级高于||。
4.dynamic_cast用于类继承多态间的转换
dynamic_cast<>用于C++类继承多态间的转换,分为:
1.子类向基类的向上转型(Up Cast)
2.基类向子类的向下转型(Down Cast)
其中向上转型不需要借助任何特殊的方法,只需用将子类的指针或引用赋给基类的指针或引用即可,dynamic_cast向上转型其总是肯定成功的。
而向下转换时要特别注意:dynamic_cast操作符,将基类类型的指针或引用安全的转换为派生类的指针或引用。dynamic_cast将一个基类对象指针(或引用)cast到继承类指针,dynamic_cast会根据基类指针是否真正指向继承类指针来做相应处理。这也是dynamic_cast与其他转换不同的地方,dynamic_cast涉及运行时类别检查,如果绑定到引用或指针的对象不是目标类型的对象,则dynamic_cast失败。如果是指针类型失败,则dynamic_cast的返回结果为0,如果是引用类型的失败,则抛出一个bad_cast错误。
注意:dynamic_cast在将父类cast到子类时,父类必须要有虚函数。因为dynamic_cast运行时需要检查RTTI信息。只有带虚函数的类运行时才会检查RTTI。
5.new和malloc的区别
new会分配内存,并调用类的构造函数创建对象,而malloc只是分配内存,不调用类的构造函数创建对象。new一般和delete连用,而malloc和free连用。
6.私有继承
私有继承中,基类的私有成员在子类中是不可访问的。并不是私有的。
7.变量的默认初始化
栈空间上面的局部变量默认初始化为随机值。
全局整形变量和静态stati整形c变量默认初始值为0。
8.运算符函数作为成员函数
思考重点在“ 成员函数”上,运算符重载为成员函数时:
成员函数隐含一个参数的this指针,所以单目运算符重载为成员函数时,无参数;双目运算符重载为成员函数时,有一个参数。
一般,单目运算符重载为成员函数;双目运算符重载为友元函数。
9.前置和后置++,- -运算符
一般情况下,优先使用前置运算符,后置运算符会带来性能问题。详细解答见《C++ Primer第五版》:
10.sizeof
sizeof用来计算某种类型占用的内存大小。如下所示:
从运行结果看: sizeof(vector<string>)
的大小为12字节,这是因为vector类中有三个指针,每个指针占4个字节,所以是三字节。无论这是一个什么类型的vector。
sizeof()用作类的对象,计算的是类中非静态成员的大小总和。对于空类来说,大小为1。
11.内存对齐
规则:
1、第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。
2、在数据成员完成各自对齐之后,类(结构或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
很明显#pragma pack(n)作为一个预编译指令用来设置多少个字节对齐的。值得注意的是,n的缺省数值是按照编译器自身设置,一般为8,合法的数值分别是1、2、4、8、16。
即编译器只会按照1、2、4、8、16的方式分割内存。若n为其他值,是无效的。
A中int占四字节,short两个字节,int四字节,short还余两个字节,不够,因此为4+2+2+4+1+3=16
B中char占1个字节,short余两个字节,够,因此为4+2+1+1+4=12