简答题
1、什么是虚函数?什么是纯虚函数?
虚函数是在类中定义函数时,在函数前加 virtual 关键字。父子类中只有一个该函数。
如果子类中没有重写该虚函数。那么父子类空间中使用的都是父类定义的该函数。
如果子类中重写了该虚函数,那么父子类空间中使用的都是子类重写的该虚函数。
如果当前类的函数设置成虚函数,那么该类的子子孙孙类中的该函数都是虚函数。
纯虚函数是定义类时,类中的某些成员函数没有实现的意义,仅仅只是该类中应该拥有的功能。
想要让子类来重写后,使用父类指针或引用指向子类对象时来调用该重写的虚函数
纯虚函数定义格式: 虚函数头 = 0;
包含纯虚函数的类,称为抽象类,抽象类是不能实例化对象的
纯虚函数需要子类进行重写,如果子类没有重写父类的纯虚函数,那么该函数在子类中也还是纯虚函数,子类也是抽象类
2、基类为什么需要虚析构函数?
当父类指针指向子类在堆区空间中的对象时,会先构造父类再构造子类,整个子类空间会全部构造出来。当使用delete关键字释放父类指针时,由于父类指针的作用域只是父类空间的内容,只能释放父类空间,子类自己的空间无法释放,导致内存泄漏。使用虚析构函数可以解决内存泄漏问题。
3、如何初始化 const 和 static 数据成员?
初始化
const
数据成员:对于const
数据成员,一般在类定义的同时被初始化。初始化
static
数据成员:static
数据成员初始化只在第一次执行时发生一次。
4、指针和引用的区别
1、引用使用标识符&,指针使用标识符*
2、没有空引用,但有空指针
3、没有多级引用,但有多级指针
4、没有引用数组,但是可以定义指针数组
5、定义引用时必须进行初始化,定义指针时可以不用初始化
6、引用一旦指定目标后,就不能进行修改了,而指针后期可以修改指向
7、引用就是目标本身,而指针记录的是目标的起始地址
8、引用不占内存空间,而指针需要占内存空间
9、引用的大小跟目标的大小保持一致,而指针的大小都是8字节(64位操作系统)
5、new 和 malloc 的区别
1、malloc\free是标准库中提供的函数,属于函数调用,而new\delete是C++中的关键字,无需开辟函数内存空间
2、malloc\free申请空间时,没有单个和连续空间的区别,而new\delete申请时区分单个和连续空间的操作
3、 malloc\free申请空间时,需要手动计算要申请空间的大小,而new\delete申请空间时,会自动计算大小
4、malloc\free申请空间时,以字节为单位,而new\delete申请空间时,以数据类型为单位
5、new申请空间时可以给空间进行初始化,而malloc不可以
6、 malloc申请出的空间结果是void*类型,使用时需要根据具体的情况进行强转,而new申请空间时,申请什么类型的空间返回的就是什么类型的指针
7、 new申请对象空间时,会自动调用该对象所在类中的构造函数,而malloc不会
8、delete释放对象空间时,会自动调用该对象所在类的析构函数,而free不会
9、 在new和delete的底层实现中,还是调用了c语言中的malloc、free
6、内存泄漏怎么产生的?如何避免?
使用
new
分配了内存,但是没有相应的delete
来释放它。如何避免:对于每次使用
new
分配的内存,都应该有相应的delete
来释放。对于使用new[]
分配的数组,应该使用delete[]
来释放。确保异常安全,即在抛出异常之前清理已分配的资源
7、C++的内存分区
代码区:存储程序的可执行代码,它是只读的,以防止程序在运行过程中被意外修改。
数据段: 已初始化数据段:存储已初始化的全局和静态变量。 未初始化数据段:存储未初始化的全局和静态变量。
堆:用于分配动态内存,程序运行时通过 malloc函数分配的内存。
栈:存储局部变量和函数调用信息(如返回地址、参数等)。当函数调用完成后,分配给这个函数的栈空间会被释放。
常量区:存储常量数据,例如字符串字面量和其他编译时常量,这个区域通常也是只读的。
8、常用的数据结构有哪些?时间复杂度和空间复杂度如何使用
数组: 时间复杂度:O(n^2) ,空间复杂度:O(n)。
链表:时间复杂度:访问,查找O(n),插入和删除O(1)。 空间复杂度:O(n)。
栈: 时间复杂度:O(1)。 空间复杂度:O(n)。
队列:时间复杂度:访问,查找O(n),插入,删除O(1)。 空间复杂度:O(n)。
哈希表: 时间复杂度:O(n), 空间复杂度:O(n)。
二叉树:时间复杂度:O(log n), 空间复杂度:O(n)。