目录
18.用代码实现构造函数,析构函数,拷贝构造函数,和拷贝构造运算符
红色字体的都是面试上面实际遇到的问题,本文只供参考
一.语法篇
1.malloc,free和new,free的区别
malloc和free都是C语言的库函数,而new和free就操作符,这样我们就可以对new和free进行重载
下面是之间的区别
1.malloc需要自己手动申请空间,new系统会自动计算申请空间;
2.分配空间异常不同:new分配空间失败的话会返回异常,malloc申请空间失败的话会返回void*
3.返回值不同:new返回对象指针,malloc返回void*,需要我们自己强转
4.new是先调用operator_new,然后申请足够的空间,再调用构造函数,初始化成员变量
malloc是根据要分配空间的大小,<128k,会在内存池或者brk上分配空间 >128k,会在mmap上分配空间
5.delete是先调用析构函数,再调用operator_delete,然后释放空间
delete后面参数是对象指针,free参数是void*
衍胜出来的问题,面试问过
free(void*)怎么知道释放空间的大小
向左偏移16个字节
malloc分配的内存是物理内存还是虚拟内存
2.介绍一下default
default是C++11的新特型,主要用于在类的声明中显式指定编译器生成默认的特殊成员函数实现。
3.C++的几种强制类型转换
1.const_cast
2.static_cast
1.用于基本数据类型之间的转换
2.将指向派生类的指针转换为基类的指针,也就是上行转换,编译器会在编译的时候检查这个派生类是否是基类的子类,所以转换的过程是安全的
3.将指向基类的指针转换为派生类的指针,也就是下行转换,编译器没有进行动态类型检查,所以是不安全的,应该使用dynamic_cast
4.在有关联的类型之间进行转换,比如转换枚举值为整数
5.将其它类型的指针转换为void*指针,比如将int类型的指针转换为void型的指针
3.dynamic_cast
dynamic_cast就做到了动态类型检查,所以就能够保证下行转换的安全性。下行转换又分两种情况,一种是基类指针指向派生类型,然后进行转换,这种转换是安全的,第二种情况是基类指针指向基类类型,这种转换就需要进行动态运行检查,转换失败,会返回NULL
4.reinterpret_cast
1.指针之间类型的转换
2.指针转换成整形,但是要注意转换的时候一定要转换到足够长的整形类型中,指针在16、32、64位操作系统下大小分别为2、4、8字节,所以在转换的时候至少要转换到对应大小的整形
3.整形转换为指针
4.介绍一下虚函数机制
虚函数机制就是为了解决C++的一些动态特性的问题,像函数的动态绑定,运行时候类型识别(RTTI);
1.在多态中,用虚函数机制,就能解决A类型指针指向B类型对象这样的问题;
基类成员函数前面加上virtual,该类函数就是虚函数,原理编译的时候编译器在类中发现virtual关键字之后,不会进行简单的对对象类型进行函数绑定,而是在运行阶段的时候根据对象的类型进行绑定;
在基类包含虚函数的时候,编译器会在对象的第一个数据成员的位置上生成vfptr(构造函数初始化),该指针指向虚函数的地址的数组,这个数组就是虚函数表
子类没有重写基类的虚函数的时候,子类继承基类的虚函数表,vfptr指向的是基类的函数
子类重写积基类的虚函数的时候,子类的虚函数表就会被覆盖,vfptr指向的是子类的函数
然后在运行的时候vfptr指向的虚函数表中找到函数的地址,然后调用函数
2.运行时候的类型识别
typeid在编译和运行的时候都可以进行类型识别,但是在运行时候进行类型识别就需要虚函数机制;
dynamic_cast 父子类的上行转换不会有问题,但是下行也就是父类转换为子类的时候,会存在越界的情况,基类加上虚函数的时候程序就不会报错了;所以保证了dynamic_cast的进行上下行转换的安全;
5.左值引用和右值引用(C++11)
6.指针和引用的区别
1.指针是一个实体,指向变量的地址,而引用是一个别称;
2.指针可以有多级,而引用只有一级;
3.声明指针变量后,可以在程序的任何地方进行初始化,引用声明完必须初始化;
4.引用不能指向空,指针可以指向空;
7.C++参数传递的三种方式
1.值传递
原变量的值不会发生变化
2.引用传递
原变量的值发生