C++重点知识整理

1、指针和引用的区别

一、32位平台下,指针是4个字节,而引用的字节数与其引用对象自己有关系。
#include<iostream>
using namespace std;
int main()
{
	int a = 10;
	char b = 'a';
	int *p1 = &a;
	char *p2 = &b;
	int &q1 = a;
	char &q2 = b;
	cout<<sizeof(p1)<<" "<<sizeof(p2)<<endl; //4  4 
	cout<<sizeof(q1)<<" "<<sizeof(q2)<<endl; //4  1
}
二、引用要进行初始化,而且一经初始化没法再改用,而指针能够更换指向,引用的底层实现是const *;
三、指针要配合*使用,才能取值,而引用则不须要,直接自带解引用功能;
四、指针存在多级指针,而引用只有一级引用(在C++11标准中,支持二级引用)。
int main()
{
	int a = 10;
	int b = 20;
	int *p1;
	//int &q1; error because:引用必需要初始化
	int &q1 = a;
	//&q1 = b; error because:一经引用不可更改
	p1 = &a;
	p1 = &b;//ok 指针是OK的

	int **pp1 = &p1;//存在多级指针 不存在多级引用
	cout<<*p1<<endl; //20  指针要配合*使用,才能取值
	cout<<q1<<endl;  //10  引用则不须要,直接就能够解引用
	return 0;
}
五、从汇编角度来看,定义引用和指针的汇编是如出一辙的,都是先把该变量的地址放到寄存器里面,再把寄存器的值交给指针或者引用变量的地址里。
int *p1 = &a;
00B44EF9  lea         eax,[a]  
00B44EFC  mov         dword ptr [p1],eax  
int &q1 = a;
00B44F05   lea             eax,[a]  
00B44F08   mov             dword ptr [q1],eax
使用指针和引用的汇编也是同样同样的,先从变量中取地址值,而后根据地址值找到里面存放的值。
cout<<*p1; //20 指针要配合*使用,才能取值 01083604 mov esi,esp 01083606 mov eax,dword ptr [p1] 01083609 mov ecx,dword ptr [eax] 0108360B push ecx 0108360C mov ecx,dword ptr ds:[1091380h] 01083612 call dword ptr ds:[1091384h] 01083618 cmp esi,esp 0108361A call __RTC_CheckEsp (0108132Ah) cout<<q1; //10 引用则不须要,直接就能够解引用 0108361F mov esi,esp 01083621 mov eax,dword ptr [q1] 01083624 mov ecx,dword ptr [eax] 01083626 push ecx 01083627 mov ecx,dword ptr ds:[1091380h] 0108362D call dword ptr ds:[1091384h] cout<<q1; //10 引用则不须要,直接就能够解引用 01083633 cmp esi,esp 01083635 call __RTC_CheckEsp (0108132Ah) 

六、指针和引用的自增(++)运算意义不同(指针移动的是地址,引用移动的是对象自己)ios

2、函数重载

函数重载是怎么回事呢?
由于C/C++都是编译型的语言,那么,就会进行符号表的生成,合并和解析等等,而C语言中的符号定义是由函数名构成,C++中的符号定义是由函数名称和参数列表决定,因此说,C++即可以构成函数重载,它的特性就是:多个函数:
一、函数名相同,参数列表不一样;(返回值不用做为参考)
二、处在同一个做用域下;
三、若是参数列表中有const,则要当心。
(const不修饰指针的状况下,和原来类型视为一致:例如:const int 和int)
补充:关键词:volitale int 和int也不能构成函数重载。
volitale的做用:(1)、防止编译器对指令顺序进行优化调整;(2)、能够防止多线程对共享变量进行缓存,可是它并不能保证对数据的原子性操做。(防止cpu对指令的调整:barrier()函数)
对原子操做的保护能够有如下几种方法:互斥锁、读写锁、自旋锁、信号量;

3、内存泄露/资源泄露的状况?

一、malloc没有free掉,new没有delete掉
二、发生浅拷贝对象默认赋值的时候,你把你的给我,而后咱两指向同一个,而后我自己的内存就泄露了;
三、基类指针指向派生类对象,而析构函数未定义成虚函数,则会致使派生类的析构函数没法调用;
四、僵尸进程未处理,丢失了进程的内核栈;
五、打开的文件没有close掉;
六、new 了一个数组,delete没写[];若是是自定义类型,则只析构了一个对象,其他99个对象都没有调用析构函数。
七、智能指针的交叉引用;
八、malloc开辟失败,则会返回NULL;new开辟失败,则会抛出一个bad_alloc异常;因此说,若是构造函数中抛出异常,则会致使析构函数没法调用,则会形成内存泄露;
九、链表的节点丢失;

4、C++多态的原理

一、静多态:只要经过重载和模板实现。
二、动多态:只要经过虚函数实现。当基类指针指向/引用派生类对象时,有虚函数的类就会生成一个虚表,这个虚表存在只读数据段内,对象一经建立,则前四个字节存的就是虚表地址,而后当这个对象访问函数的时候,就会经过这个地址找到虚表,虚表的实现通常是同名覆盖,只要子类实现的函数就会覆盖父类的,因此就能够经过虚表里面的函数地址,找到真正的函数。

5、早绑定/晚绑定?静态绑定和动态绑定?

早期绑定是指在函数的入口地址已经在编译时所有计算完整,操做系统装入程序直接装入程序计算函数的入口地址,因此,在编译阶段决定执行哪一个同名的被调用函数,这叫作静态绑定。
晚期绑定则是指在运行阶段才决定执行哪一个函数,又叫动态绑定。其实现即是虚函数,如上题。