来源:https://www.nowcoder.com/discuss/57978
如何消除隐式转换?
面经解释:使用explicit关键字进行修饰
自己补充:explicit关键字修饰,一般来说加了肯定比不加好,主要用来针对隐式的强转
例子:
class A{ public: A(const string &a ):x(a),y(0),z(0); int compare_to(A z){ return this.x>z.x; } string x; int y,z; } int main(){ A z; z.compare_to("123"); //这里因为拷贝构造函数只是一个string ,会隐式的创建成 A对象,一般根据业务的需要判断要不要着这种强转 }
重载,重写和隐藏的区别?
面经解释:重载:即函数重载
重写【覆盖】:即用于虚函数
隐藏:只要派生类的函数名与基类相同就会隐藏
补充:
重载作用域只是限于同一个类中,然后要求是参数列表和原来的有所不同,无论是类型还是个数,返回值无所谓
重写作用域发生在不同类中,限于父类中加了virual关键字,然后子类重写,要求名字参数列表返回值都完全一样,只能修改执行体,重写完这个函数默认属于父类
隐藏作用域发生在不同类中,要求只要名字一样,实现出来,就会隐藏掉父类中的方法,无法调用
volatile表示什么?有什么作用?
面经解释:易变的,不会被编译器进行优化,让程序取数据直接去内存中的。
补充:编译器有些时候会自带一些优化,把没有必要的一些代码给优化掉,编译器每次取值会优先从缓存里面去读取,如果是多线程和汇编的一些命令情况下,缓存会来不及修改
而产生错误,所以我们要表明这个变量是经常改变的, 所以我们让他略过这个去缓存的过程直接去内存取值
Malloc和new的区别?
面经解释:
New:
内存分配错误时,抛出bad_alloc异常,可以定义set_new_handler函数来在产生异常时进行处理;本身是一个运算符;分配内存的地方为自由存储区【为一个抽象概念】;对于对象而言,会先申请内存空间然后调用构造函数;无需指定大小
Malloc:
内存分配错误时,返回NULL;本身是一个库函数;分配内存的地方为堆;只申请内存空间;需要指定申请多大的内存;
free和delete的区别?
Delete:
本身是一个运算符
Free:
本身是一个库函数
free一个数组时如何知道要释放多大的内存呢?
一般在数组前面几个字节中存在某一个结构体来保存当前申请的数组大小。
引用和指针的区别?
指针:是一个变量类型;指针可以不进行初始化;指针初始化后可以改变,在写代码时需要大量的检测
引用:是一个别名;引用必须要初始化;引用初始化后不可改变,无需检测
Linux 内部有哪些调试宏
_FILE_ : 表示在哪个文件
_LINE_ : 表示在哪一行
_FUNCTION_ : 表示在哪个函数
出现异常时 try,catch在做什么
try 作用域里面的代码也叫保护代码,如果里面的代码发送错误,就会由catch检测出来,具体什么错误看catch里面捕捉的类型,然后再由throw抛出异常,抛给上一级
C++如何处理多次异常
多次catch
常对象的成员变量一定不可以修改吗?为什么?
不一定,可以使用mutable关键字修饰,代表是可变的,无论什么情况下,该变量都是可以改变的
应用场景:如果你一个常函数,你里面大部分都不能修改,但是有一个要,为了保证整体的常属性,就可以用mutable进行修饰
虚函数调用过程
现在内存对象中找到虚函数指针,然后利用虚函数指针找到虚函数表,在虚函数表中找到对应的虚函数
单继承,多继承,菱形继承内存怎么样,如果存在虚函数怎么样
都是直接进行继承的,内存里面都会存在,像多继承,如果调用相同名函数,前面就要加类名强调,有虚函数的话会继承多个虚函数表
实现一个vector?是1.5还是2倍,各有什么优缺点?
1.5倍好,这个倍数也叫扩容因子,当vector当前内存到边界的时候就要动态扩容,扩容1.5倍或者2倍,扩容的时候会把之前那段内存舍弃,然后去找
一段新的内存来存储,会把之前的值都赋值过来,这样的话1.5倍后面申请就有可能再次用到之前的空间(如果多次申请,然后前几次堆在一起成了一块的话)
总结:复用之前申请的内存,不用去开辟新的内存,这里体现空间优势
2倍,一次申请这么多,就能节省申请次数,因为申请空间也要时间,这里体现时间优势
如果用map删除了一个元素,迭代器还能用吗?为什么?怎样做可以接着用?
可以使用,你只是删除了当前迭代器,但是不影响你进行++操作移到下一个去
红黑树五大特征?
1,节点非红即黑
2,红色节点的儿子都是黑色
3,根节点为黑色
4,叶子为黑色
5,任意节点到叶子节点的所有路径经过的黑色节点数不会差一倍
红黑树如何插入和删除的?
插入:
(1)如果父节点为黑色,直接插入不处理
(2)如果父节点为红色,叔叔节点为红色,则父节点和叔叔节点变为黑色,祖先节点变为红色,将节点操作转换为祖先节点
(3)如果当前节点为父亲节点的右节点,则以父亲结点为中心左旋操作
(4)如果当前节点为父亲节点的左节点,则父亲节点变为黑色,祖先节点变为红色,以祖先节点为中心右旋操作
删除:
(1)先按照排序二叉树的方法,删除当前节点,如果需要转移即转移到下一个节点
(2)当前节点,必定为这样的情况:没有左子树。
(3)删除为红色节点,不需要处理,直接按照删除二叉树节点一样
(4)如果兄弟节点为黑色,兄弟节点的两个子节点为黑色,则将兄弟节点变为红色,将着色转移到父亲节点
(5)如果兄弟节点为红色,将兄弟节点设为黑色,父亲结点设为红色节点,对父亲结点进行左旋操作
(6)如果兄弟节点为黑色,左孩子为红色,右孩子为黑色,对兄弟节点进行右旋操作
(7)如果兄弟节点为黑色,右孩子为红色,则将父亲节点的颜色赋值给兄弟节点,将父亲节点设置为黑色,将兄弟节点的右孩子设为黑色,对父亲节点进行左旋
线程同步几种方式?
互斥锁 信号量 临界区
手写strcpy,memcpy,memmove函数?
三个的区别
strcpy是对字符进行的拷贝
memcpy是对任何类型的拷贝,但是他没有考虑到两个指针指向区域有重合的情况
memmove 任何类型的拷贝,考虑到重合情况,目标地址在左边的话,那么高地址赋值的来
char *mystrcpy(char *p,char *q){ char *h=p; while((*p++=*q++)!='