C++常考⾯试题⽬
const的作⽤
修饰函数的参数和返回值(后者应⽤⽐较少,⼀般为值传递) const成员函数(只需要在成员函数参数列表后加上关键字const,如char get() const;)可以访问const成员变量和⾮const成员变量,但不能修改任何变量。在声明⼀个成员函数时,若该成员函数并不对数据成员进⾏修改操作,应尽可能将该成员函数声明为const成员函数。const对象只能访问const成员函数,⽽⾮const对象可以访问任意的成员函数,包括const成员函数.即对于class A,有const A a;那么a只能访问A的const成员函数。⽽对于:A b;b可以访问任何成员函数。 使⽤const关键字修饰的变量,⼀定要对变量进⾏初始化
C++11有什么新特性:
1.auto可与for循环结合
2.nullptr
3.智能指针
多线程:在C++11以前,C++的多线程编程均需依赖系统或第三⽅接⼝实现,⼀定程度上影响了代码的移植性。C++11中,引⼊了boost 库中的多线程部分内容,形成C++标准,形成标准后的boost多线程编程部分接⼝基本没有变化,这样⽅便了以前使⽤boost接⼝开发的使⽤者切换使⽤C++标准接⼝,把容易把boost接⼝升级为C++接⼝。 左值引⽤与右指引⽤:
先看⼀下传统的左值引⽤:
int a =10;
int&b = a;// 定义⼀个左值引⽤变量
b =20;// 通过左值引⽤修改引⽤内存的值
右值引⽤:
int&&var =10;
可以取地址的,有名字的,⾮临时的就是左值;
不能取地址的,没有名字的,临时的就是右值;
static:
1.全局静态变量
在全局变量前加上关键字static,全局变量就定义成⼀个全局静态变量.
静态存储区,在整个程序运⾏期间⼀直存在。
在局部变量之前加上关键字static,局部变量就成为⼀个局部静态变量。
内存中的位置:静态存储区
函数的实现使⽤static修饰,那么这个函数只可在本cpp内使⽤,不能被其他⽂件所⽤。
在类中,静态成员可以实现多个对象之间的数据共享,静态成员属于类
重载和重写:
重载:两个函数名相同,但是参数列表不同(个数,类型),返回值类型没有要求,在同⼀作⽤域中
重写:⼦类继承了⽗类,⽗类中的函数是虚函数,在⼦类中重新定义了这个虚函数,这种情况是重写
请你来说⼀下静态函数和虚函数的区别:
静态函数在编译的时候就已经确定运⾏时机,虚函数在运⾏的时候动态绑定。虚函数因为⽤了虚函数表机制,调⽤的时候会增加⼀次内存开销
为什么基类析构器都是虚函数?
动态库和静态库的区别:
静态库在程序编译时会被连接到⽬标代码中,程序运⾏时不再需要静态库;⽽动态库在程序编译时,不会放到连接的⽬标代码中,⽽是在程序运⾏时被载⼊,因此在程序运⾏时还需要动态库的存在。
虚拟内存:
它使得应⽤程序认为它拥有连续的可⽤的内存(⼀个连续完整的地址空间),⽽实际上,它通常是被分隔成多个物理内存碎⽚
⼀个线程只能属于⼀个进程,⽽⼀个进程可以有多个线程,但⾄少有⼀个线程。线程依赖于进程⽽存在。
进程是资源分配的最⼩单位,线程是CPU调度的最⼩单位;
进程间不会相互影响 ;线程⼀个线程挂掉将导致整个进程挂掉
进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进⾏通信——需要进程同步和互斥⼿段的辅助,以保证数据的⼀致性。
进程间通信的⽅式:
进程间通信主要包括管道、系统IPC(包括消息队列、信号量、信号、共享内存等)、以及套接字socket。
TCP 如何保障数据包有效:
校验和
确认应答+序列号
滑动窗⼝和 拥塞控制(四种控制⽅法:慢开始/拥塞避免/快重传/快恢复)
滑动窗⼝:
为什么是三次握⼿:(为什么要发第三次出来)
现假定出现⼀种异常情况,即A发出的第⼀个连接请求报⽂段并没有丢失,⽽是在某些⽹络结点长时间滞留了,以致延误到连接释放以后的某个时间才到达B。本来这是⼀个早已失效的报⽂段。但B收到此失效的连接请求报⽂段后,就误认为是A⼜发出⼀次新的连接请求。于是就向A发出确认报⽂段,同意建⽴连接。假定不采⽤三次握⼿,那么只要B发出确认,新的连接就建⽴了。
四次挥⼿为什么要等times2倍:
**为了保证A发送的最后⼀个ACK报⽂段能够到达B。**这个 ACK报⽂段有可能丢失,因⽽使处在LAST-ACK状态的B收不到对已发送的FIN +ACK报⽂段的确认。B会超时重传这个FN + ACK报⽂段,⽽A就能在2MSL 时间内收到这个重传的FIN + ACK报⽂段。接着A重传⼀次确认,重新启动2MSL 计时器。最后,A和B都正常进⼊到CLOSED状态。
防⽌上⼀节提到的“已失效的连接请求报⽂段”出现在本连接中。A在发送完最后⼀个 ACK 报⽂段后,再经过时间2MSL,就可以使本连接持续的时间内所产⽣的所有报⽂段都从⽹络中消失。这样就可以使下⼀个新的连接中不会出现这种旧的连接请求报⽂段。
HTTPS 和 HTTP 的区别:
http是超⽂本传输协议,信息是明⽂传输,https则是具有安全性的ssl/tls加密传输协议
内核态和⽤户态的划分与切换:
执⾏权限不同
执⾏空间不同
⽤户到内核的切换:
中断,系统调⽤,异常
算法类:
BN:
加快⽹络的训练和收敛的速度
控制梯度爆炸防⽌梯度消失
防⽌过拟合
如何防⽌过拟合:
1.Dropout
2.正则化(Regularization)
随机梯度下降和梯度下降的区别:
随机梯度下降是随机⼀个样本取样替代完整的样本
多态的实现是虚函数表
malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型
信号(软中断)⽤来和进程之间通信的⼀个⽅式。
#include< >和#include“ ”的区别:
1.引⽤的头⽂件不同 #include< >引⽤的是编译器的类库路径⾥⾯的头⽂件。 #include“ ”引⽤的是你程序⽬录的相对路径中的头⽂件。管道:
管道主要包括⽆名管道和命名管道:管道可⽤于具有亲缘关系的⽗⼦进程间的通信,有名管道除了具有管道所具有的功能外,它还允许⽆亲缘关系进程间的通信
批处理系统、分时系统和实时系统中,各采⽤哪⼏种进程(作业)调度算法?
批处理系统常⽤调度算法:
①、先来先服务:FCFS
②、最短作业优先
③、最短剩余时间优先
④、响应⽐最⾼者优先
分时系统调度算法:
①、轮转调度
②、优先级调度
③、多级队列调度
④、调度
实时系统调度算法:
①、单⽐率调度
②、限期调度
③、最少裕度法
线程通信:
volatile
等待唤醒机制(wait,notify)
join⽅式
threadLocal
排序算法:
拷贝构造函数:
下⾯是⼀个复制构造函数的例⼦。
#include<iostream >
using namespace std;
class Complex
{
public:
double real, imag;
Complex(double r,double i){
real= r; imag = i;
}
};
int main(){
Complex cl(1,2);
Complex c2(cl);//⽤复制构造函数初始化c2 cout<&al<<","<<c2.imag;//输出 1,2 return0;
}
第 13 ⾏给出了初始化 c2 的参数,即 c1。只有编译器⾃动⽣成的那个默认复制构造函数的参数才能和 c1 匹配,因此,c2 就是以 c1 为参数,调⽤默认复制构造函数进⾏初始化的。初始化的结果是 c2 成为 c1 的复制品,即 c2 和 c1 每个成员变量的值都相等。
const常量与指针:
const int*m1 = new int(10);
int*const m2 = new int(20);
在上⾯的两个表达式中,最容易让⼈迷惑的是const到底是修饰指针还是指针指向的内存区域?其实,
只要知道:const只对它左边的东西起作⽤,唯⼀的例外就是const本⾝就是最左边的修饰符,那么它才会对右边的东西起作⽤。根据这个规则来判断,m1应该是常量指针(即,不能通过m1来修改它所指向的内容。);⽽m2应该是指针常量(即,不能让m2指向其他的内存模块)
常量类型的函数只有权读取外部数据内容,但⽆权修改他们。
<;类型说明符><;函数名>(<;参数表>)const;
memcopy实现:
void*my_memcpy(void*dst,const void* src, size_t size)
{
if(dst ==NULL|| src ==NULL|| size <=0)
return dst;
char* dst_pos =(char*)dst;
char* src_pos =(char*)src;
while(size >0){
*dst_pos++=*src_pos++;
size --;
}
return dst;
}
线程安全与线程不安全:
线程安全问题都是由全局变量及静态变量引起的。
线程安全是指多个线程在执⾏同⼀段代码的时候采⽤加锁机制,使每次的执⾏结果和单线程执⾏的结果都是⼀样的,不存在执⾏结果的⼆义性。
线程不安全就是不提供加锁机制保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据
有哪些可以解决多线程并发访问资源的安全问题呢?
有三种⽅式:分别是 同步代码块 、同步⽅法和锁机制(Lock)
内联函数与宏定义区别:
(1)内联函数在编译时展开,宏在预编译时展开;
(2)内联函数直接嵌⼊到⽬标代码中,宏是简单的做⽂本替换;
(3)内联函数有类型检测、语法判断等功能,⽽宏没有;
(4)inline函数是函数,宏不是;
(5)宏定义时要注意书写(参数要括起来)否则容易出现歧义,内联函数不会产⽣歧义;
Linux中查的命令主要是:grep和find:
区别:grep是根据⽂件的内容进⾏查,会对⽂件的每⼀⾏按照给定的模式进⾏匹配查。
find是根据⽂件的属性进⾏查,如⽂件名,⽂件⼤⼩,所有者,所属组,是否为空,访问时间,修改时间。