C++关键字辨析
1、new/delete、malloc/free
- malloc与free是C++/C语言的标准库函数,仅用于申请动态内存和释放内存
- new与delete是C++的运算符,可用于申请动态内存和释放内存。另外,new能完成动态内存分配和初始化工作(调用构造函数),delete能完成清理与释放内存工作(调用析构函数)。 适用于处理非内部数据类型的动态对象。(对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数)
2、delete 与 delete[]
- 对于内建简单数据类型,delete和delete[]的功能相同(由于内部数据类型没有析构函数);对于自定义的复杂数据类型,不能互用
- delete 只会调用一次析构函数,用于删除一个指针,与new配套
- delete[] 会调用每一个成员的析构函数,用于数组时,为每个数组元素调用析构函数,然后调用operator delete释放内存。与new[]配套
3、C++的多态性(virtual)与虚函数
- 程序运行时的多态性:继承和虚函数。
- 程序编译时的多态性:函数与运算符的重载
虚函数:
在类的继承层次结构中,在不同的层次中可以出现名字相同,参数个数和类型都相同而功能不同的函数。编译器根据同名覆盖原则决定调用的对象。例如派生类对象cy1.area()调用的是派生类的成员函数area(),要想使用派生了对象调用基类的area函数,需使用cy1.Circle::area(),指明area()函数所属类。这种方法可以区分两个同名的函数,但很不方便。
为了能够使用同一种调用形式既能调用派生类又能调用基类的同名函数,使用虚函数,这样我们就可以通过基类指针的动态绑定调用不同派生层次的函数。只需要在调用前给基类指针变量赋予不同的值(使之指向不同的类对象)。参考这儿。
将基类的析构函数声明为虚函数的作用: 例如 当new了一个派生类对象并赋值给基类指针时,Base* p=new Derive(),若基类的析构函数不是虚函数,当使用delete释放内存时,只会调用基类的析构函数,派生类的构造函数将不会被调用(非动态绑定),导致内存泄露。
4、引用与常引用(const int &)
- 引用是给某个变量取别名。引用声明时要被初始化,且初始化后不能再重新被赋值。不能建立数组的引用。
- 传递引用给函数与传递指针效果一样,且不产生实参的副本,直接对实参进行操作。(传递指针虽然也能达到使用引用的效果,但是需要给形参分配存储单元,且必须使用变量的地址作为实参,并使用"* 指针变量名"进行运算)
- 常引用:利用引用可以提高程序效率,使用const又能保护传递给函数的数据不在函数中被改变。 const int & ra=a;
- 将引用作为函数返回值类型:在内存中不产生返回值的副本。(注意(1)不能返回局部变量的引用:因局部变量在函数返回后会被销毁;(2)不能返回函数内部new分配的内存的引用:因容易导致内存泄露,即由引用所指向的空间无法被释放;(3)返回类成员的引用最好是const:由于其他属性或对象状态容易导致赋值时该成员改变;(4)流操作符<<和>>重载,赋值操作符重载时返回值申明为引用:这样可以连续使用如x=j=10(赋值操作符的返回值必须是一个左值,以便可以被继续赋值),cout<<“hello”<<endl;)
5、重载(overload)与重写(或称覆盖,overried)
- 重载指允许存在多个同名函数,但函数的参数表不同(参数个数或参数类型不同)。对于编译器而言,这些同名函数属于不同的函数,地址在编译器就绑定了
- 重写指子类重新定义父类虚函数的方法,用于实现多态性,函数的地址在运行期绑定
6、initialization list 与 assignment
- 当类中含有const、reference成员变量时,基类的构造函数需要使用初始化表
7、类型安全
- C++不是类型安全的,两个不同类型的指针之间可以强制转换(reinterpret cast)。C#是类型安全的。
8、内存分配方式
- 全局变量以及static变量从静态存储区域分配:内存在程序编译时就已分配好,存在于整个程序运行期
- 局部变量分配在栈上:函数执行结束存储单元自动被释放
- new动态申请的内存从堆上分配,由程序员主动释放
9、static
用途:
(1)限制变量的作用域;
- 模块内声明(但在函数体外)的静态函数或静态变量只能被这一模块内的函数所调用或访问,所声明的静态函数只能在本地范围内使用(所声明的静态变量是一个本地全局变量)
(2)设置变量的存储域。
- 函数体内声明的静态变量在函数被调用过程中维持其值不变。(其内存在静态存储区域分配,在程序编译时分配,在程序的整个运行期间存在,因此在函数返回时并不会被释放。)
10、const
const int a; // a 为整型常量
int const a; // 与 const int a 相同
const int *a; // a 为一个指向整型常量的指针(整型量不可修改,指针可修改)
int * const a; // a 为一个指向整型数的常指针(整型数可修改,指针不可修改)
int const * a const; // a为一个指向整型常量的常指针(整型数不可修改,指针不可修改)
11、enum枚举
// 默认编译器设置第一个枚举量为0,下一个枚举量为上一个枚举量+1
// 注意:若赋值必须是整数
enum Roster {Tom, Sharon, Bill, Teresa, John}; // 定义枚举类型
Roster student; // 定义枚举变量
student = Sharon; // 枚举变量赋值