C/C++面试经历(一)

目录

1. 说说你对C与C++的认识? 

2. 说说C++的三大特性?

3. 说说C++的重载?

4. C语言为什么不支持重载?

5. 说说类的默认成员函数?

6. 类的构造函数为什么不支持虚函数?

7. 说说你对指针和引用的理解?

8. 说说你对栈与堆的理解?

9. 说说map和unordered_map的区别?

10. 说说哈希和哈希碰撞?


1. 说说你对C与C++的认识? 

C语言是更偏底层的面向过程编程语言,C语言程序员需要了解并认识系统级的接口,并且能够熟练的对系统资源进行分配和调度。

C++是基于C语言的面向对象编程语言,C++程序员需要有抽象思维能力,将实际的问题转换为一个对象模型从而解决问题。

总的来说,C++是兼容C语言的,并且对C语言做了一些封装和扩展,从而能更便捷的实现编码。

2. 说说C++的三大特性?

C++的三特性分别是封装、继承和多态。

封装是将属性和操作封装在一个类中,隐藏内部的实现过程,只对外提供必要的接口,提高代码的安全性。

继承是指一个类可以通过继承另一个类的属性和方法来扩展自己的功能,提高代码的重用性,增加了类与类之间的耦合性。

多态是在继承的基础上,让一个接口能够实现多种的功能,通过父类指针或引用调用子类的接口,增加了接口的重用性。

3. 说说C++的重载?

C++的重载是指在同一个作用域内,对一个函数或者运算符进行多种定义,使其能够通过不同的参数类型或参数个数实现不同的功能。

运算符重载包括关系运算符、下标运算符、输入输出运算符重载,对某个类的小括号进行重载,可以使某个类变为仿函数。

4. C语言为什么不支持重载?

无论是C语言还是C++程序在从源代码生成可执行程序的过程中,都会经过预处理、编译、汇编、链接四个步骤,而C语言不能支持重载但是C++能够支持重载的原因就在链接这个步骤上。

在链接时,会生成符号表,C语言的设计存在缺陷,符号表里面的函数名就是函数名本身,当多个相同的函数名被定义的时候,在链接这个步骤相同的函数名不同的参数也是一样的命名,就会产生冲突而报错。

但是C++通过g++进行编译链接时在符号表中对于函数的命名规则是不一样的,C++符号表中的函数名由其函数名本身和参数构成,在链接这个步骤相同的函数名不同的参数就会在符号表中有不同的命名。

5. 说说类的默认成员函数?

C++的6大默认成员函数分别是构造、析构、拷贝构造、赋值运算符重载、取地址运算符重载和const修饰的取地址运算符重载。

6. 类的构造函数为什么不支持虚函数?

调用虚函数需要维护一张虚函数表,每一个拥有虚成员函数的类都有一个指向虚函数表的指针。

从存储角度来说,对象通过虚函数表里存储的虚函数地址来调用虚函数,但是虚函数表是在构造函数中进行初始化。当我们new一个对象的时候,第一步是申请空间,第二步便是调用构造函数,此时虚函数表不可能存在,故无法让构造函数作为虚函数从而通过虚函数表调用。

从使用角度来说,虚函数的调用是在信息不全的条件下,能使重载的函数得到对应的调用。要创建一个对象,需要知道一个对象的确切类型,因此构造函数不能被定义为虚函数。

7. 说说你对指针和引用的理解?

指针是指向一个数据地址的变量,存放的是数据的地址信息。

引用是一个数据的别名,通过对某个数值的引用进行修改,这个数值本身也会修改。

对比来说,指针可以为空、可以改变指向、可以有多级,别名不能为空且必须初始化、不能改变指向、只有一级,指针的自增自减是表示指向下一个或上一个同类型数据的地址,引用的自增自减是让所指向的变量的值进行自增自减操作。

8. 说说你对栈与堆的理解?

从内存管理角度来说,栈和堆处于内存的不同存储区域,栈区由操作系统自动分配,存储局部变量,堆区由程序员通过new或者malloc接口申请空间做资源存储,当资源使用完毕需要程序员主动释放,否则会造成系统资源浪费,通过free接口释放资源的时候还要注意野指针问题。

从数据结构角度来说,栈是连续的存储空间结构,支持随机访问,遵从“先进后出”规则,程序的执行也是通过函数栈帧的实现的,堆是完全二叉树结构,通过堆的调整策略将最值存入堆顶,常用于Top K的算法。

9. 说说map和unordered_map的区别?

map和unordered_map都是STL封装的容器,存放的数据是KV键值对。

map是通过对红黑树的封装实现的,红黑树对数据的增、删、查、改都有着非常高的效率,红黑树数据插入时能够根据键值自动排序。

unordered_map是通过对哈希表的封装实现的,哈希表的数据增、删、改的效率和红黑树差不多,但是哈希表的数据查询效率远高于红黑树,哈希表数据在插入时并不保证元素顺序,即无序的map。

总之,根据红黑树和哈希表性质的不同,在需要有序的遍历数据时,应选择map,当需要快速定位元素时,应选择unordered_map。

10. 说说哈希和哈希碰撞?

哈希也称散列,哈希算法是指将任意长度的输入通过散列运算得到一个固定长度的输出,该输出就是哈希值。

通常情况下,散列值的空间小于输入值的空间,并且哈希运算是不可逆运算,即可以通过原值得到哈希值,但是却不能通过哈希值推算出原值。

哈希碰撞是指两个不同原值,经过某种哈希运算之后得到了一个一样的哈希值,这就是哈希碰撞,也叫哈希冲突。

哈希碰撞的解决办法有开放寻址法和拉链法,开放寻址法也叫闭散列哈希表,拉链法也叫开散列哈希桶。

先说闭散列,当某个位置发生哈希冲突后,后面的数据就放到下一个位置,如果下一个位置也被占用了,则继续寻找直到找到空位置,闭散列的负载因子是已存入数据和空间容量的比值,当负载因子大于某个值时,会扩容并遍历已存入的数据重新映射。

再说开散列,将哈希冲突的值以链表的形式串起来存储在某个位置,负载因子同样是已存入数据和空间容量的比值,当负载因子大于某个值时进行扩容,并且改变已存入数据的指针使其重新映射。

你可能感兴趣的:(随笔闲谈,c语言,c++,开发语言)