百度C++一面-面经总结
1、你知道网络编程服务端建立连接的流程吗?把用到的api
说出来?
server:
1.socket()
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
2.bind()
struct sockaddr_in serv_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY; // 监听所有本地地址
serv_addr.sin_port = htons(PORT); // 绑定的端口号
bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
3.listen()
listen(sockfd, backlog);
4.accept()
int newsockfd = accept(sockfd, (struct sockaddr *)&client_addr, &client_len);
5.read()/write()
6.close()
2、服务端需要设置端口号吗?客户端呢?端口号在哪个api中自动绑定的?端口号有什么作用?如果两个程序使用同一个端口号会怎么样?端口号的范围是多少?哪里限制了端口号的范围?
1.服务端需要显式设置端口号:bind
而客户端不需要显式设置端口号,自动分配临时的。
2.在bind()这个api中自动绑定的。
3.端口号主要为了区分主机上运行的不同服务。http用80,https用443,ssh用22。
4.用了同一段口,后一个程序将会“地址已在使用”错误。
5.有效端口号:0-65535
0-1023是知名端口号,非特权程序不能bind
6.端口号的范围是65535,就是16位整数,因为这是tcp/ip协议栈在os中定义的。最大值就是(2^16 - 1)
。
3、你知道linux用什么命令查找端口号吗?
netstat -tuln//老牌的网络工具
ss -tuln//显示所有正在监听的 TCP 和 UDP 端口。
4、UDP和TCP?TCP头部有哪些内容?TCP怎么保证可靠连接的?
1.连靠刘墉宿营
2.TCP头部有:
源端口号-目的端口号-序列号-确认号-数据偏移-保留位-控制位-窗口大小-校验和-紧急指针
3.保证可靠连接:
1.三次握手(Three-way Handshake):在建立连接时,TCP 使用三次握手确保双方确认彼此的存在,并同步初始序列号,避免早期的旧数据干扰。客户端发送 SYN 包(同步序列号)请求连接。服务器收到 SYN 后返回 SYN-ACK 包确认连接。客户端收到 SYN-ACK 后再发送 ACK 包,完成连接建立。2.确认应答机制(ACK):每个数据包在发送后,接收方会发送一个确认应答(ACK)包,告知发送方已成功接收。发送方只有在收到 ACK 后,才认为数据成功传送。
3.重传机制:如果发送方没有在预期时间内收到 ACK,TCP 会自动重传数据,确保丢失的数据段被重新发送。
4.序列号与重排序:每个数据包都有唯一的序列号,接收方根据序列号来重组数据,确保数据按正确顺序到达。
5.流量控制:通过窗口大小(Window Size)字段,TCP 控制数据传输速度,避免发送方发送过快导致接收方处理不过来。
6.拥塞控制:TCP 使用如慢启动、拥塞避免等算法来检测网络拥塞,并根据网络情况动态调整传输速度,确保不会因过载导致网络崩溃。
7.四次挥手(Four-way Teardown):TCP 连接结束时通过四次挥手过程来保证连接的可靠关闭,确保双方都有机会传输剩余的数据。
5、说一说网络的TCP/IP四层模型的作用?
物联网淑慧适用-七层
四层的:
应用层:HTTP FTP DNS SMTP
传输层:TCP UDP(加了tcp头)
网络层:IP (加了ip头)
网络接口层:链路级别 (加了帧头)
作用:
高内聚低耦合
模块化
标准化协议
互操作性
6、TCP是那一层的,IP呢?说一说DNS的工作流程是怎么样的?
传输层,网络层
DNS:将人类可读的域名解析成计算机可以处理的IP地址
缓存-本地DNS-根-顶级-权威
7、你能介绍一下什么是重载吗?你知道重载和重写的区别吗?
允许在同一个作用域中定义多个同名的函数或方法,但这些函数具有不同的参数列表。编译器通过参数的个数、类型或顺序来区分这些函数调用。这种机制使得函数可以根据不同的参数类型或数量实现不同的功能。函数名相同,但参数类型、数量或顺序不同。
重写:则是继承中出现的子类重定义了方法,虚函数来实现,且需要在父类中声明为virtual。函数名、参数列表和返回类型必须与父类的虚函数一致。
8、你了解虚拟内存吗?进程间的通信方式有哪些你了解吗?
物理内存和磁盘存储的结合,为每一个进程都提供独立连续的地址空间。提高稳定性,利用率。(不够用就内存扩展,隔离为虚拟地址,还可以简化内存管理,不用关心物理内存了 交给os)
虚拟内存主要是通过os的页表将虚拟地址转换为物理地址,如果不在物理内存,就会页面置换,不常用的页面写入磁盘,所需页面从磁盘加载到内存。
管道 消息队列 共享内存 信号量 socket 信号 文件 等等。
9、用户态和内核态的区别是什么,用户态怎么转到内核态,是自动转换的吗?
不同的CPU执行模式
用户态:受限的权限,无法访问内核内存,限制系统资源的访问,出现错误也不会导致系统崩溃
内核态:最高权限,可以访问全部内存
不是自动转换 不是自动转换 不是自动转换
机制:
1.系统调用
2.中断
3.异常
但是内核态回到用户态通常自动的
10、C++与C相比有什么好处?
面向对象
标准模板库
类型安全
函数重载
运算符重载
命名空间
11、C++11有哪些新特性?
1.auto关键字:自动推导
2.范围for:简化遍历
3.智能指针:用于管理动态分配的内存,帮助防止内存泄漏。
4.lambda表达式:函数内部定义匿名函数 提高灵活性
5.nullptr:替代了传统NULL
6.强制类型转换 更安全
7.右值引用和移动语义 提高对临时对象的处理效率。
8.新的容器 unordered_map set
9.原生支持多线程
12、你了解智能指针吗?
std::shared_ptr:引用计数为0就释放
多个指针共享同一块内存:
std::shared_ptr<int> sharedInt = std::make_shared<int>(42);
std::shared_ptr<int> anotherSharedInt = sharedInt; // 共享同一块内存
std::unique_ptr:单一所有权
std::weak_ptr:协助shared_ptr避免循环引用
其中多个shared_ptr互相引用,导致内存泄漏。
std::auto_ptr是个辣鸡 不用了
13、类的缺省函数有哪些?(就是自己不写也会有默认的函数)
-
缺省构造函数
作用:无参数构造函数,用于创建类的实例时不传递参数。
特征:如果类中没有定义任何构造函数,编译器会自动提供一个缺省构造函数。 -
拷贝构造函数
作用:用于通过另一个同类型对象来初始化一个对象,即复制对象。
特征:如果类中没有定义拷贝构造函数,编译器会自动提供一个。默认的拷贝构造函数执行逐成员复制。 -
移动构造函数
作用:用于将一个对象的资源“移动”到另一个对象,避免不必要的复制。
特征:当类中没有定义移动构造函数时,编译器会提供一个默认实现,通常会将资源的所有权转移给新对象。 -
赋值运算符
作用:用于将一个对象的值赋给另一个已存在的同类型对象。
特征:如果类中没有定义赋值运算符,编译器会提供一个默认实现。默认赋值运算符执行逐成员复制。 -
移动赋值运算符
作用:用于将一个对象的资源“移动”到另一个已存在的对象,避免不必要的复制。
特征:当类中没有定义移动赋值运算符时,编译器会提供一个默认实现。 -
析构函数
作用:在对象生命周期结束时自动调用,用于清理资源(如动态内存、文件句柄等)。
特征:如果类中没有定义析构函数,编译器会提供一个默认的析构函数,该函数会自动释放所有成员的资源。
14、构造函数是先执行基类构造还是子类构造?析构函数呢?
先执行基类的构造:保证基类在子类的重写之前被正确初始化。
析构函数是先析构子类的,保证安全清理基类。
15、Windows创建线程的函数是什么,创建进程的呢?pthread_create有哪些参数,分别有哪些作用?父线程的pthread_create返回值是什么,pthread_detach()函数的作用?
就是CreateThread、CreateProcess
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
参数说明:
pthread_t \*thread:用于存储新线程的 ID 的指针。
const pthread_attr_t \*attr:指向线程属性对象的指针,可以为 NULL,表示使用默认属性。这个参数可以用于设置线程的栈大小、调度策略等。
void \*(\*start_routine)(void \*):线程的起始例程,线程运行时将调用这个函数。该函数必须返回 void * 类型的值,并接收一个 void * 类型的参数。
void \*arg:传递给线程起始例程的参数,可以是任意类型的指针,在线程内部可以通过强制转换来访问。
返回值:成功就是0,不成功就是错误代码。
pthread_detach(pthread_t thread) 用于将线程设置为“分离状态”,使得线程在结束时自动释放其资源
,而不需要被其他线程调用 pthread_join 来回收。避免资源泄漏,适用于那些不需要等待线程结束结果的情况。
16、如果子线程退出,父线程没有捕捉子线程的信息会有什么影响?那如果父线程先退出呢,子线程会怎么样?
父线程用pthread_join() 获取子线程的返回值
如果没有捕捉到
那么子线程的资源不会被释放,资源泄漏。
子线程僵尸状态,等待join()
如果父线程退出了,如果子线程独立的话,那就不影响。如果依赖的话,那就导致不确定状态,尤其是子线程依赖父线程的某些资源。
talk is cheap show me the code。