派生类和基类中有同名的函数,但非虚函数。基类指针会调用哪个的函数,如何调用另一个类的这个函数呢。如果是虚函数有会怎样呢?
答:派生类和基类中有同名的函数,但非虚函数。基类指针会调用基类的函数。当如果是虚函数的话,则要看基类指针指向的是派生类还是基类。是谁就调用谁的。子类不是现基类的函数。会调用基类的函数,基类指针指向子类对象,调用非虚函数函数时,会调用基类函数。基类指针可以通过子类的虚函数调用子类的非虚函数。
虚函数表指针在头部还是在哪 跟编译器有关吗?
** 答:****虚函数的地址存放于虚函数表之中。运行期多态就是通过虚函数和虚函数表实现的。**
类的对象内部会有指向类内部的虚表地址的指针。通过这个指针调用虚函数。目前gcc 和微软的编译器都是将vptr放在对象内存布局的最前面。
函数重载的条件
答:同一个作用域下 ****函数名称相同 ****函数参数类型不同 或者 个数不同 或者 顺序不同 函数的返回值不可以作为函数重载的条件
STL容器常见的时间复杂度。
map, set, multimap, and multiset
上述四种容器采用红黑树实现,红黑树是平衡二叉树的一种。不同操作的时间复杂度近似为:
插入: O(logN) ****查看:O(logN) ****删除:O(logN)
hash_map, hash_set, hash_multimap, and hash_multiset
上述四种容器采用哈希表实现,不同操作的时间复杂度为:
插入:O(1),最坏情况O(N)。 ****查看:O(1),最坏情况O(N)。 ****删除:O(1),最坏情况O(N)。
多继承虚函数表
答:多继承情况下,派生类中有多个虚函数表,虚函数的排列方式和继承的顺序一致。派生类重写函数将会覆盖所有虚函数表的同名内容,派生类自定义新的虚函数将会在第一个类的虚函数表的后面进行扩充。
深拷贝、浅拷贝
深拷贝优点:每一个对象的指针都有指向的内存空间,而不是共享,所以在对象析构的时候就不存在重复释放和内存泄漏的问题。
缺点:内存开销大
浅拷贝优点:通过拷贝构造函数实例化对象的时候,指针数据变量指向共享的内存空间,也就是拷贝的时候采用了值传递的方式,因此内存开销小
缺点:对象析构的时候就可能会重复释放或造成内存泄漏;
strcpy()的代码实现
其安全版本为strcpy_s()函数,(第二个参数,为字符串dst的长度)。
image多进程与多线程的区别
强相关的处理用线程,弱相关的处理用进程。
线程同步方式:互斥锁、条件变量、信号量,读写锁
1>互斥锁:一个时间内只准一个线程进入关键代码
2>条件变量:利用线程之间共享一个全局变量是实现同步;基本操作有:触发条件(当条件为true时),等待条件,挂起线程直到其他线程触发条件
3> 信号量:跟进程的信号量一样
4>读写锁:多个读锁可以共享一个临界区,写锁与写锁互斥,写锁与读锁互斥
image哈希冲突产生的原因
哈希是通过对数据进行再压缩,提高效率的一种解决方法。但由于通过哈希函数产生的哈希值是有限的,而数据可能比较多,导致经过哈希函数处理后仍然有不同的数据对应相同的值。这时候就产生了哈希冲突。
1.开放地址方法:就是在发生冲突的key上加1或者n的平方或者一个随机值;
2.链式地址法(HashMap的哈希冲突解决方法):对于相同的值,使用链表进行连接。使用数组存储每一个链表。
3.建立公共溢出区: 建立公共溢出区存储所有哈希冲突的数据。
4.再哈希法:对于冲突的哈希值再次进行哈希处理,直至没有哈希冲突。
static
**答:分为两种 **
面向过程中的static:
static局部变量 将一个变量声明为函数的局部变量,那么这个局部变量在函数执行完成之后不会被释放,而是继续保留在内存中
static 全局变量 表示一个变量在当前文件的全局内可访问
static 函数 表示一个函数只能在当前文件中被访问
(1)函数体内static变量的作用范围为该函数体,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;
(2)在模块内的static全局变量和函数可以被模块内的函数访问,但不能被模块外其它函数访问;
面向对象的static关键字:static对象 类内声明 类外初始化 编译阶段分配内存 所有对象共享同一份数据。
** static函数:在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,只能调用static成员变量;程序共享同一个函数。**
const:
const 常量:定义时就初始化,以后不能更改。
const 形参:func(const int a){};该形参在函数里不能改变
const修饰类成员函数:该函数对成员变量只能进行只读操作
(1)阻止一个变量被改变
(2)声明常量指针和指针常量
(3)const修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
(4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;
(5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为”左值”。
extern
只是用来获取全局变量(包括全局静态变量)的值,不能用于定义变量,先在当前文件查找有没有全局变量,没有找到,才会去其他文件查找。
排序算法的稳定性
答:选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
image空指针和野指针:
答:空指针指针变量指向内存中编号为0的空间,一般用来初始化指针变量,空指针指向的内存是不可以访问的。
** 野指针是指针变量指向已销毁或者受限的内存地址(随机的空间),不能通过是否为null来判断。当指针初始化没有置空时,也会产生野指针。或者指针超越了作用域。**
map/unordered_map的区别
内部实现机理不同
map: map内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树,而AVL是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。map中的元素是按照二叉搜索树(又名二叉查找树、二叉排序树,特点就是左子树上所有节点的键值都小于根节点的键值,右子树所有节点的键值都大于根节点的键值)存储的,使用中序遍历可将键值按照从小到大遍历出来。
unordered_map: unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。哈希表详细介绍
优缺点以及适用处
map:
优点:
有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作
红黑树,内部实现一个红黑书使得map的很多操作在lgn的时间复杂度下就可以实现,因此效率非常的高
缺点: 空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间
适用处:对于那些有顺序要求的问题,用map会更高效一些
unordered_map:
优点: 因为内部实现了哈希表,因此其查找速度非常的快
缺点: 哈希表的建立比较耗费时间
适用处:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map
总结:
内存占有率的问题就转化成红黑树 VS hash表 , 还是unorder_map占用的内存要高。
但是unordered_map执行效率要比map高很多
对于unordered_map或unordered_set容器,其遍历顺序与创建该容器时输入的顺序不一定相同,因为遍历是按照哈希表从前往后依次遍历的
map和unordered_map的使用
unordered_map的用法和map是一样的,提供了 insert,size,count等操作,并且里面的元素也是以pair类型来存贮的。其底层实现是完全不同的,上方已经解释了,但是就外部使用来说却是一致的。
strcpy和memcpy和strncpy
strcpy和memcpy主要有以下3方面的区别。
1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy
strncpy 的标准用法为:(手工写上 \0)
strncpy(path, src, sizeof(path) - 1);
path[sizeof(path) - 1] = '\0';
len = strlen(path);
1. 好的程序猿用strncpy, 先定义并初始化char str[MAX + 1] = {0};, 如果在程序中间需要再往str中拷贝串,一定要用memset清零。 拷贝范式为:strncpy(str, p, sizeof(str) - 1); , 流氓程序猿用strcpy, 当然我经常在写博客时这么干.
2. strncpy拷贝的是字符,不拷贝串,所以最后一个\0没有拷贝,所以,拷贝的时候需要对串进行清零处理,一定要养成好习惯。
3. strncpy拷贝时,可能会导致截断,但程序不会崩溃。
网友评论