C/C++面试总结

一、计算机网路相关知识点

1、TCP/UDP区别和联系

①、TCP面向连接的,UDP面向无连接
②、TCP面向字节流的,UDP是基于报文的
③、TCP可靠传输,UDP不可靠传输,可能会丢包
④、TCP是全双工的,只能一对一通信,UDP支持一对一、一对多、多对一、多对多传输通信
⑤、TCP 保证数据按序发送,UDP不保证数据按序发送

2、TCP三次握手

(1)、第一次握手,建立连接时,客户端发送SYN包到服务端,进入SYN_SENT状态,等待服务器确认。(SYN:不同序列编号)
(2)、第二次握手,服务器收到SYN包后,确认是客户端发送的SYN包,于是自己发送一个SYN包,即SYN+ACK包此时服务器进入SYN_RECV状态。
(3)、第三次握手,客户端收到服务器发送的SYN+ACK包后,下高服务器端发送ACK包,此时发送完毕,建立三次握手成功,客户端和服务器端都进入ESTABLISHED。

3、SocKet

1> Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。
2> 在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议
族隐藏在接口后面,对客户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定协议。
3> 门面模式,其实就是对外界提供一个简单的接口,外界不需要知到其内部实现过程。

二、C/C++相关知识点

1、C++注册表编程

注册表的组织方式跟文件目录相似,分别位根键、键值、子健三部分组成,与文件目录对应的话就是目录、子目录、文件

1.1、 根键

HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
HKEY_CURRENT_CONFI
把它们理解成磁盘的五个分区就可以了

1.2、子健

可以有很多个子健和键值项,就像一个目录中有多个子目录和文件一样

1.3、键值项

可以理解成文件,它由三部分组成,分别为名称、数据、类型
类型又分为多种主要包括如下:
    REG_BINARY 二进制数据
    REG_DWORD 32位双字节数据
    REG_SZ 以0结尾的字符串
    REG_DWORD_BIG_ENDIAN 高位排在底位的双字
    REG_EXPAND_SZ 扩展字符串,可以加入变量如%PATH%
    REG_LINK UNICODE 符号链接
    REG_RESOURCE_LIST 设备驱动程序资源列表
    REG_MULTI_SZ 多字符串
注册表数据项的数据类型有8种,但最常用的主要是前3种。
有了这些基础下面我们讨论如何编程实现对注册表的操作。

2、vector

(1). 容量
向量大小: vec.size();
向量最大容量: vec.max_size();
更改向量大小: vec.resize();
向量真实大小: vec.capacity();
向量判空: vec.empty();
(2). 修改
多个元素赋值: vec.assign(); //类似于初始化时用数组进行赋值
末尾添加元素: vec.push_back();
末尾删除元素: vec.pop_back();
任意位置插入元素: vec.insert();
任意位置删除元素: vec.erase();
交换两个向量的元素: vec.swap();
清空向量元素: vec.clear();
(3)迭代器
开始指针:vec.begin();
末尾指针:vec.end(); //指向最后一个元素的下一个位置
(4)元素的访问
下标访问: vec[1]; //并不会检查是否越界
at方法访问: vec.at(1);//以上两者的区别就是at会检查是否越界,是则抛出out of range异常
访问第一个元素: vec.front();
访问最后一个元素: vec.back();

vector类为内置数组提供了一种替代表示,与string类一样 vector 类是随标准 C++引入的标准库的一部分 ,为了使用vector 我们必须包含相关的头文件 :
#include
使用vector有两种不同的形式,即所谓的数组习惯和 STL习惯。

3、sort函数

sort() 函数受到底层实现方式的限制,它仅适用于普通数组和部分类型的容器。换句话说,只有普通数组和具备以下条件的容器,才能使用 sort() 函数:

  1. 容器支持的迭代器类型必须为随机访问迭代器。这意味着,sort() 只对 array、vector、deque 这 3 个容器提供支持。

  2. 如果对容器中指定区域的元素做默认升序排序,则元素类型必须支持<小于运算符;同样,如果选用标准库提供的其它排序规则,元素类型也必须支持该规则底层实现所用的比较运算符;

  3. sort() 函数在实现排序时,需要交换容器中元素的存储位置。这种情况下,如果容器中存储的是自定义的类对象,则该类的内部必须提供移动构造函数和移动赋值运算符。

  4. 另外还需要注意的一点是,对于指定区域内值相等的元素,sort() 函数无法保证它们的相对位置不发生改变。

4、构造函数和析构函数

构造函数和析构函数用来创建和释放该类的对象,当这个类是派生类时,其对象的创建和释放应与其基类对象及成员对象相联系。
在声明派生类时,一般还应当自己定义派生类的构造函数和析构函数,因为构造函数和析构函数是不能从基类继承的
派生类对象的创建和初始化与基类对象的创建和初始化有关。即构造派生类对象时,要对其基类数据成员、所含对象成员的数据成员以及其他的新增数据成员一起进行初始化。这种初始化工作是由派生类的构造函数来完成的。
派生类成员包括两部分:
(1)从基类继承的成员:由基类构造函数完成
(2)自身定义的成员: 由派生类构造函数完成
调用基类构造函数的两种方式:
(1)显式方式:在派生类的构造函数中,通过参数化表为基类的构造函数提供参数
derived::derived(arg_derived-list):base(arg_base-list)
(2)隐式方式:在派生类/基类的构造函数都缺省时,派生类的构造函数则自动调用基类的默认构造函数。

5、内联函数

在C++中我们通常定义以下函数来求两个整数的最大值:
复制代码 代码如下:

int max(int a, int b)
{
return a > b ? a : b;
}
为这么一个小的操作定义一个函数的好处有:
① 阅读和理解函数 max 的调用,要比读一条等价的条件表达式并解释它的含义要容易得多
② 如果需要做任何修改,修改函数要比找出并修改每一处等价表达式容易得多
③ 使用函数可以确保统一的行为,每个测试都保证以相同的方式实现
④ 函数可以重用,不必为其他应用程序重写代码

6、深拷贝和浅拷贝

编译系统在我们没有自己定义拷贝构造函数时,会在拷贝对象时调用默认拷贝构造函数,进行的是浅拷贝!即对指针name拷贝后会出现两个指针指向同一个内存空间。所以,在对含有指针成员的对象进行拷贝时,必须要自己定义拷贝构造函数,使拷贝后的对象指针成员有自己的内存空间,即进行深拷贝,这样就避免了内存泄漏发生。
当对象中存在指针成员时,除了在复制对象时需要考虑自定义拷贝构造函数,还应该考虑以下两种情形:
1.当函数的参数为对象时,实参传递给形参的实际上是实参的一个拷贝对象,系统自动通过拷贝构造函数实现;
2.当函数的返回值为一个对象时,该对象实际上是函数内对象的一个拷贝,用于返回函数调用处。
3.浅拷贝带来问题的本质在于析构函数释放多次堆内存,使用std::shared_ptr,可以完美解决这个问题。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_44585751

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值