咸鱼翻身之C++面试准备(一)

这几天被单纯的小美好洗脑,每天都活在粉红泡泡里面,hahaha

为了让自己心安,于是决定把之前准备的一些面试的东东分享出来,希望大家都能找到一个好的归宿......

一,多态的类中内存布局是怎样的?

(1)普通的类:成员变量按照声明的顺序进行排列,成员函数不占用存储空间

(2)继承:子类继承父类的成员变量,在内存排布上,先排布父类的成员变量,再排布子类的成员变量,成员函数不占字节

(3)给父类加一个virtual函数

父类中的内存布局:

虚表指针------->vptr

                          父类成员变量

(4)在子类中加一个virtual函数,子类就会继承父类的虚表指针

子类中的内存布局:

虚表指针-------->vptr

                          父类成员变量

                          子类成员变量

(5)子类中重新定义了一个虚方法

Base::fun()

Derived:fun1()

用父类的指针pd-->子类的对象pb    pd->fun();父类的fun();

                                                              pd->fun1();子类中的fun1();

(6)子类中既覆盖了父类中的虚函数,也添加了新的虚函数

用父类的指针pd-->子类的对象pb    pd->fun();子类的fun();

                                                              pd->fun1();子类中的fun1();

(7)多重继承

Base

Derived1:public Base

Derived2:public Base

Derived3 public Derived1, public Derived2

Base的内存布局:

虚表指针------->vptr

                          成员变量


Derived1和Derived2的内存布局

虚表指针------->vptr

                           父类成员变量

                           子类成员变量

Derived3:

虚表指针-->vptr                       虚表指针-->vptr

排布父类                                   排布父类

排布子类                                   排布子类

(两份虚表)

(8)虚继承:减少对基类的重复继承

Base

Derived1 :virtual public Base

Derived 2: virtual public Base

Derived 3: public Derived1, public Derived2

Base的内存布局:

虚表指针----->vptr

                        成员变量

Derived1和Derived2的内存布局:

虚表指针---->vptr1=====>指向虚基类对应的虚表

                        Base

虚表指针---->vptr2======>指向Derived1的虚表

父类成员变量

子类成员变量

(虚继承有两份虚指针)

Derived3的内存布局

虚表指针----->vptr1======>指向虚基类对应的虚表

Base

虚表指针----->vptr2======>指向Derived1的虚表

虚表指针------>vptr3=====>指向Derived2的虚表

总结:

当基类中有虚函数时:

(1)每个类都有虚指针和虚表

(2)如果不是虚继承,子类将父类的虚指针继承下来,并指向自己的虚表

(3)如果是虚继承,子类就会有两份虚表,一份指向自己的虚表,另一份指向虚基表 ,多重继承时虚基表和虚指针只有一份

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

二.extern"C"的作用

extern 关键字表明函数和全局变量作用范围的关键字,告诉编译器,其声明的函数和变量可以在本模块或者其他模块使用

extern"C"修饰的变量和函数是按照C语言方式编译和连接的,请看例子:

我们知道C++支持函数重载,C不支持函数重载,C++编译后在符号库中的名字与C不同

void fun(int x, int y)

C:_fun

C++:_fun_int_int<包含函数名,参数的数量和类型>

extern"C"告诉编译器:找_fun 而不是_fun_int_int

用法:

在CPP文件中添加extern"C",在Cyu语言中仅将C++中定义的extern"C"函数声明为extern类型

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------三.unordered_set的底层数据结构

unordered_set和unordered_map是C++中出现的两种新的关联式容器,内部实现与set,map不同,set,map的底层是红黑树,而unordered_set的底层是哈希表

哈希表是根据关键码进行直接访问,通过相应的哈希函数处理关键字得到相应的关键码,关键码对应一个特定的位置,用来存储相应的信息,以较快的速度获得关键字的信息

unordered_set特点:

存在唯一键值(无重复),元素无秩序

如果空间不足,扩容时与vector类似,但每次扩容都要对表中的数据重新计算


---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 四.隐式类型转换与显示类型转换

(1)隐式类型转换:编译器私下进行的类型转换行为

C++的內建类型:char, double, int 默认有隐式转换

(低精度-------》高精度)

看一个特别的例子:

class string
{
   public:
     string(const char *p);
};

string s1 = "hello";
//隐式转换  string s1 = string("hello");
如果要避免隐式转换需要加关键字explicit

(2)显式转换(强制类型转换:之前有一篇专门写这个)

static_cast

dynamic_cast

const_cast

reinterpret_cast

static_cast

  • 编译器隐式执行的任何类型都可以是static_cast完成
  • 类层次之间可以进行上行(把子类的指针或者引用转化为基类)/下行(把基类的指针或者引用转换为子类)转换
  • 在进行下行转换时没有类型安全检查

dynamic_cast

  • 涉及类型安全检查,运行时类型安全检查,需要运行时的类型信息,这个信息存储在类的虚函数中,所以用dynamic_cast的类中必须有虚函数
  • 进行上行转换时效果和static_case效果相同
  • 进行下行装换时会进行类型的安全检查

const_cast

  • 转换表达式的const性质:添加或者删除const性质

reinterpret_cast

  • 相当于()   int *p;   char *ptr = (char *)p; 

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

五.服务器和客户端的建立过程

主要是通过socket套接字,在应用层和传输层之间建立一个抽象层,建立TCP/IP复杂的通信,把通信转化为接口供应用层调用来实现网络通信

                服务器                                                                   客户端

创建套接字socket                                                             创建套接字socket

绑定套接字bind                                                                 连接指定的计算机端口connect

监听套接字listen                                                                向socket中写入数据send()

接受来自客户端的请求accept                                          关闭socket     close

从socket中读字符      recv

关闭套接字                  close

相关过程:

服务器根据地址类型创建socket------------>服务器为socket绑定ip地址和端口号------------->服务器socket监听端口号请求,随时准备接受客户端发来的连接,此时服务器的socket还没有打开------------------>客户端创建socket----------------------->客户端打开socket,根据ip地址和端口号试图连接服务器socket--------------->服务器socket收到客户端socket的连接请求,被动打开,接收客户端请求,直到客户端返回连接信息-------------------------->客户端连接成功,向服务器发送连接状态信息----------->服务器accept方法返回,连接成功

----------------->客户端向socket中写数据------------------------>服务器从socket中读数据-------------->客户端关闭------------------->服务器关闭

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------六.TCP与UDP的区别

  • TCP是面向连接的,UDP是无连接的
  • TCP要求的资源多,UDP要求的资源少
  • TCP是流模式,UDP是数据报模式
  • TCP保证数据的正确性,UDP可能会出现乱序,丢包的可能
  • TCP提供充分的数据传输过程中的各种传输机制,丢包重发,对次序乱掉的包进行顺序的控制,只有在确认对端存在时才会发送数据,可以避免对流量的浪费
  • UDP不提供复杂的控制机制,只提供作为传输层协议最基本的功能,将部分的功能转移到应用程序中去处理
  • 具体编程的区别:
  • socket参数不同,TCP参数为SOCK_STREAM,表示socket用于流式通信,具有可靠性和有序性;UDP的参数为SOCK_DGRAM是无连接的,不可靠的,通信双方发送数据之后不知道对方是否已经接收到数据
  • UDP的服务端不需要监听(listen),接收(recv)
  • TCP发送接收数据用recv/send ,UDP用sendto/recvfrom
  • UDP在sendto/recvfrom函数中每次都需要指定地址信息,TCP在accept/connect时地址信息已经确定

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  七.大小端

采用小端模式的CPU对操作数的存储方式是从低字节到高字节

采用大端模式的CPU对操作数的存储方式是从高字节到低字节

0x1234

小端:

0x01                    0x34

0x02                    0x12                       

大端:

0x01                    0x12

0x02                    0x34      

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------八,UDP适用场景

  •  面向数据报模式
  • 拥有大量客户端
  • 对网络的安全性没有要求
  • 网络负担重,对于响应速度要求非常高            

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

九.TCP和UDP的编程对比

TCP

服务器端                                 客户端

创建一个socket                     创建一个socket

绑定bind                                 连接connect

监听listen                                send/recv

接收accept                              关闭连接close

发送send/recv

关闭close


UDP

服务器端                                  客户端

创建socket                               创建socket

绑定bind                                   发送sendto

循环接收recvfrom                    关闭连接close

关闭网络连接

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

十,select,poll,epoll

(1)select

  • 用途:在一段时间内监听用户感兴趣的文件描述符上的可读,可写,异常事件
  • 五个参数:第一个参数指定被监听的最大文件描述符的个数,通常被设置为select监听的所有文件描述符的最大值+1,第二个,第三个,第四个参数分别指向可读,可写,异常事件的集合,应用程序调用select时,通过这三个参数传入自己感兴趣的文件描述符,select调用返回时,内核将通过修改他们来通知应用程序那些文件描述符已经准备就绪
  • select成功调用,返回就绪的文件描述符的个数
  • 每次调用select时,就必须对这三个参数进行重置
(2)poll
  • poll与select相似,在指定时间内去轮询一定数量的文件描述符,以测试其中是否有就绪的文件描述符
  • 封装成一个结构体,里面包含注册的时间和实际发生的时间
  • 内核通过修改实际发生的事件来通知应用程序实际上发生了哪些事件
(3)epoll
  • 通过一组函数来完成epoll_create  epoll_ctl   epoll_wait
  • epoll把用户关心的文件描述符的事件放在一个事件表中,不需要像select,poll每次都要重新传入文件描述符和事件集
  • 需要一个额外的文件描述符来唯一标示内核中的这个事件表,由epoll_create创建,用epoll_ctl来操作这个事件表
  • epoll_wait在一段超时时间内等待一组文件描述符上的事件,第二个参数用来传出epoll_wait检测到的就绪事件,如果检测到事件,就把所有就绪时间从内核事件表中复制到第二个参数中,不会像select,poll的参数既用于传入用户注册的事件,又用于输出内核检测到的就绪事件


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值