百度面试
1、手写vector删除元素,需要注意迭代器失效情况。
int a[3]={1,2,3};
vector<int> v(a,a+3);
vector<int>::iterator it=v.begin()+2;
if(it<v.end())
v.erase(it);
2、手写两个类,要体现构造,析构,拷贝构造,赋值,虚函数,重载函数等特点。
A类有变量x,b类有变量y 重载+号
class A{
public:
A(int i):x(i){}
A(const A &a){
x=a.x;
}
int x;
virtual void print(){
cout<<"x="<<x<<endl;
}
};
class B:public A{
public:
B():A(0){y=0;} //重载构造函数
B(int i,int j):A(i),y(j){} //构造函数
int y;
B(const B &b):A(b.x){ //拷贝构造函数
y=b.y;
}
virtual void print(){ //虚函数
cout<<"x="<<y<<endl;
}
B operator=(const B &b){ //重载=值号
if(this==&b) return *this;
x=b.x;
y=b.y;
return *this;
}
};
3、析构函数为什么为虚函数?
4、new跟malloc的区别?
5、free是如何识别free区域的
每个内存区域前面都有一个管理信息,free函数把内存区域前面的管理信息标志位置1,然后操作系统根据内存的标志位来确定是否释放该段内存。
6、Linux何如找到目录中cpp文件?如何找文件中一变量?
7、Linux检测内存泄露?
Valgrind工具进行内存泄露检测和性能分析
8、了解哪些开源项目?
9、n级台阶问题
10、一致性哈希
11、如何判断一个图是否有环
12、讲一个你觉得很完美的代码或开源项目
13、traceroute有什么优势?
15、介绍一个比较完整的项目,画出流程图
16、STL中vector内存分配?如何从原内存拷贝的新内存?会调用构造函数么?
17、软件工程?
软件工程是:1.将系统化的、严格约束的、可量化的方法应用于软件的开发、运行和维护,即将工程化应用于软件;
18、如何看待C++面向对象?与c有何区别?
19、面向对象设计原则?里氏替换是指什么?
单一职责原则、里氏替换原则、接口隔离原则、开闭原则、依赖倒置原则
20、C++接口与实现 (抽象类、纯虚函数)
21、多态是如何实现的?画一下虚指针与虚函数表,如果多继承,虚函数表怎么画?
22、虚指针是对象成员变量么?在什么时候初始化?
不是,因为没有名字,但是可以调用。初始化是编译器完成,应该在类创建的时候初始化。
23、讲一下TCP中拥塞控制
24、C++中强制类型转换?Dynamic_cast的作用
25、多态是如何实现的?
26、C++中构造函数发生异常会怎样?
27、C++中构造函数中this指针暴露了会有什么后果?
比如把this指针转换为其他类型指针来访问类中的私有成员变量,破坏类的封装性。
28、互斥锁和自旋锁
两种锁的加锁原理
互斥锁:线程会从sleep(加锁)——>running(解锁),过程中有上下文的切换,cpu的抢占,信号的发送等开销。
自旋锁:线程一直是running(加锁——>解锁),死循环检测锁的标志位,机制不复杂。
两种锁的区别
互斥锁的起始原始开销要高于自旋锁,但是基本是一劳永逸,临界区持锁时间的大小并不会对互斥锁的开销造成影响,而自旋锁是死循环检测,加锁全程消耗cpu,起始开销虽然低于互斥锁,但是随着持锁时间,加锁的开销是线性增长。
两种锁的应用
互斥锁用于临界区持锁时间比较长的操作,比如下面这些情况都可以考虑
1 临界区有IO操作
2 临界区代码复杂或者循环量大
3 临界区竞争非常激烈
4 单核处理器
至于自旋锁就主要用在临界区持锁时间非常短且CPU资源不紧张的情况下。
自旋-互斥锁
下面的英文介绍了混合互斥锁和混合自旋锁,但是不管是第一段说的先上非阻塞锁后上阻塞锁,还是第二段说的先自旋上锁后进行休眠,反正思路都是先自旋上锁一定时间后在上互斥锁,这种自旋-互斥锁适合各线程持锁时间间隔跨度比较大的情况。