C++复习

常见的面试题汇总(持续更新)

2018-06-11  本文已影响12人  凉拌姨妈好吃

Get与Post之间的区别

因为Get和Post都是Http里发送协议的两种方法。它们都是TCP连接,所以它们做的事情都是一样的,如果非要给Get加上requeat body,给Post带上url参数,在技术上都是可行的。
对于Get请求,浏览器会将http header和data一起发送给服务器。
而Post请求是先发送header,得到服务器的相应后,再发送data。
以及传输数据大小、安全性方面的区别。

同步通信与异步通信

异步通信就是发送方任意时刻都可以发送数据,前提是接收方要做好接收数据的准备。因为发送方的不确定性,所以接收方要时时刻刻准备接收数据,同时由于每次发送数据时间间隔的不确定性,所以每次发送的时候都要用明确的界定符来标识数据的开始和结束位置。( 不需要发送端与接收端时钟同步,发送端发送数据后,可以隔任意时间长后再发数据)

同步通信就是在通信之前需要先建立同步,即要使用相同的时钟频率,发送方的发送频率要与接收方的接收频率相同。

它们之间的区别:发送接收方时钟频率、发送数据的表现形式(同步:比特流、异步:字符)、(通信效率、简单性都可以从时钟频率那里看出区别)

为什么TCP一定要三次握手

假设它们现在只进行一次握手,这根本不可能的,A发送消息给B,根本不知道B有没有收到,那A就无法判断有没有连接上B。

假设此时它们只进行二次握手,A发送消息给B,等待B的回应,但是现在因为网络延迟的原因没有及时发送给B,A在一段时间后没有收到B的回应消息,会再次发送同样的消息给B。现在网络不延迟了,B会收到A的两个消息,它会为这两个消息申请资源,然后分别返回SYN给A,但对于A来说,第一个SYN已经是过期了的,它不再理会。而B不知道第一个过期了,B始终维护着那个连接,这就会造成资源浪费。

操作系统执行可执行程序时,内存分配是怎样的

堆区:动态内存分配。如果频繁分配大小不同的内存很容易产生堆内存块。
栈区:由系统自动分配释放,存放函数的参数值、局部变量的值。
全局区(静态存储区):内存在程序编译期间就分配好,这块内存在整个程序运行期间都存在,主要存放全局变量、静态变量等。
文字常量区:他们里面存放的是常量(常量字符串等),不允许修改,程序结束后由系统释放
程序代码区:存放函数体的二进制代码
C和C++内存分配方式记录

堆与栈的对比(从内存分布来看)

1. 管理方式不同:堆由程序员自己进行内存的释放和申请,栈是由编译器控制的。
2. 空间大小不同:堆内存大,几乎没有限制,栈内存较小。
3. 能否产生碎片:堆内存由于是程序员自己动态申请的,频繁的申请和释放不同大小的内存会造成一定数量的内存块。而栈内存是先进后出的,永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出,所以之间不可能产生内存碎片。
4. 生长方向:堆空间向着内存地址增加的方向生长,栈空间向着内存地址减少的方向生长。
5. 分配效率:栈是底层的数据结构,底层对栈提供了各种各样的支持以至于栈的分配效率高。而堆是由C++提出的,它的申请内存的过程都会经历一个复杂的算法,去堆里找到适合的内存再返回。

在VS编译器下,为什么成员函数模板不能是虚函数(virtual)

编译器期望在处理类的定义的时候就知道虚函数表的大小,如果允许有类的虚成员模板函数,那么就必须要求编译器提前知道程序中所有对该类的该虚成员模板函数的调用,而这是不可行的。

C++中,重载、重写、重定义的区别

重载在同一作用域内,函数名相同,参数列表不同,返回值可能不同。调用函数名相同的函数,会根据实参的类型和实参顺序以及实参个数选择相应的函数,这就叫做静态联编。

int Add(int a,int b)
{
    return a+b;
}
float Add(float a,float b)
{
    return a+b;
}

重写:重写的前提条件是父类的该函数为虚函数,子类在定义了父类同名虚函数的时候就是称为重写了父类虚函数。
重定义不同作用域内,不构成重写的都为重定义。如果在父类和子类中有相同名字的成员;那么在子类中。会将父类的成员隐藏

乐观锁与悲观锁

乐观锁:当线程进入一个临界区的时候,它会乐观的认为它执行的时候不会有其他线程的影响,所以不需要上锁。
乐观锁的实现:给数据库的表增加一个version字段,每更新一次version+1,。也就是先查询那条记录,获取version字段,当我们需要更新之前,再查询一次,将已经查询的version与刚刚查询的version做比较,如果不相等就不更新,相等就更新再把version+1。

悲观锁:当线程进入一个临界区的时候,它会悲观的认为它执行的时候一定有其他线程的影响,所以需要上锁。
共享锁、排它锁都是悲观锁。

Windows编程中,消息机制如何实现?

  1. 自定义消息
  2. 头文件声明函数
  3. 在消息映射中添加对应关系

两个小数相乘,小数点后位数没有限制,请写出高精度算法
输入 string a, string b; 计算string c=a*b; 返回 c;

  1. 记录a的小数点位置locationA,b的小数点位置locationB,最后c的小数点位置为length(a)+length(b)-locationA-locationB-2
  2. 去掉ab的小数点,变为大整数相乘
  3. 输出c,在刚才记录的c的小数点的位置输出小数点

下面我们看看大整数相乘

void multiply(char* a,char* b,char* c)

{
    int i,j,ca,cb,* s;
    ca=strlen(a);
    cb=strlen(b);
    s=(int*)malloc(sizeof(int)*(ca+cb));
 // strlen(a)的数a * strlen(b)的数b一定少于strlen(a)+strlen(b)的数

// 初始化数组
    for (i=0;i<ca+cb;i++)
{
        s[i]=0;
}
// 各个位上的数分别相乘,并存入相应位的数组成员中(原理类似于小学的两个数相乘的方式)
    for (i=0;i<ca;i++)
        for (j=0;j<cb;j++)
            s[i+j+1]+=(a[i]-'0')*(b[j]-'0');
 //这里为什么不是s[i+j]?而是s[i+j+1]
------为了统一操作,s[0]是用来存放最高位的进位,否则需要分开进行判断

//
 处理有进位的数位
    for (i=ca+cb-1;i>=0;i--)
{
        if (s[i]>=10)
        {
            s[i-1]+=s[i]/10;
            s[i]%=10;
        }
}

// 清除高位的0
    i=0;
    while (s[i]==0)
        i++;
       for (j=0;i<ca+cb;i++,j++)
           c[j]=s[i]+'0';
    c[j]='\0';
    free(s);
}

两个整数集合A和B,求其交集两个整数集合A和B,求其交集。

  • 读取整数集合A中的整数,将读到的整数插入到map中,并将对应的值设为1。
  • 读取整数集合B中的整数,如果该整数在map中并且值为1,则将此数加入到交集当中,并将在map中的对应值改为2。通过更改map中的值,避免了将同样的值输出两次。

UDP协议通信时如何得知接收方有接收到包

发送方在发送包的时候给数据包加上ID信息,在发送数据时要把这个包暂时保存在本地。接收方接收到包的时候将ID发回给发送方,发送方就知道包发送成功。

类的静态成员函数为什么不能调用非静态成员

类的员静态成员函数在类加载的时候就会分配内存员,而类的员非静态成员只有在类实例化员之后才会存在,所以我们在静态成员函数里调用非静态成员就相当于拿一个已经存在的去调用一个未知的东西。

静态链接与动态链接的区别

动态链接是把调用函数的dll模块链接进程序,在程序运行的时候才到dll下找到需要相应的函数代码。该dll不会包含在生成的exe中,可以在exe中动态卸载和引用这个dll文件。
静态链接是把所有的代码和数据都复制到本模块中,也就是生成的exe里存在这些代码,运行就不需要库了。

死锁产生的必要条件

互斥:资源不能被共享,只能同一个进程使用
请求和保存:已经得到资源的进程可以再次申请资源
循环等待:若资源被占用,那该进程就等待在那里,不做其他事
不剥夺:已经分配的资源不能从进程中剥夺

上一篇下一篇

猜你喜欢

热点阅读