面试题目:STL详解+Map学习+计网……

目录

1.STL

2.map详解

3.内存分配之alloca、calloc、malloc、free、realloc等

4.计算机网络四层模型

5.为什么是四次挥手,不是三次?

6.什么时候使用静态变量和静态函数

 7.多个类同时访问一个对象,怎么办?

 8.全局变量在使用过程中有没有遇到过什么问题?

 9.一个静态的对象,可以访问一个非静态的方法吗?

 10.类的构造函数和成员的构造函数的顺序

11.构造函数能抛异常吗?析构函数?

12.假设我发现有大量的close_wait状态,你觉得是出了什么问题呢?

13. Mysql的常用引擎?

14.怎么理解可重复读?

15.C++空类的sizeof计算出来的大小是多少

16.菱形继承的解决办法


1.STL

(1)STL(Standard Template Library,标准模板库),

STL 从广义上分为: 容器(container) 算法(algorithm) 迭代器(iterator),

容器和算法之间通过迭代器进行无缝连接。STL 几乎所有的代码都采用了模板类或者模板函数,这相比传统的由函数和类组成的库来说提供了更好的代码重用机会

(2)STL的六大组件

容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器

(3)STL优点

STL 是 C++的一部分,因此不用额外安装什么,它被内建在你的编译器之内。
STL 的一个重要特性是将数据和操作分离。数据由容器类别加以管理,操作则由可定制的算法定义。迭代器在两者之间充当“粘合剂”,以使算法可以和容器交互运作
程序员可以不用思考 STL 具体的实现过程,只要能够熟练使用 STL 就 OK 了

STL 具有高可重用性,高性能,高移植性,跨平台的优点。

(4)容器:STL容器就是将运用最广泛的一些数据结构实现出来。
常用的数据结构:数组(array) , 链表(list), tree(树),栈(stack), 队列(queue), 集合(set),映射表(map), 根据数据在容器中的排列特性,这些数据分为序列式容器和关联式容器两种

(5)vector容器基本概念

vector的数据安排以及操作方式,与array非常相似,两者的唯一差别在于空间的运用的灵活性

Array是静态空间,一旦配置了就不能改变,要换大一点或者小一点的空间,可以,一切琐碎得由自己来,首先配置一块新的空间,然后将旧空间的数据搬往新空间,再释放原来的空间

Vector是动态空间,随着元素的加入,它的内部机制会自动扩充空间以容纳新元素

 参考:【C++】STL学习小总结_ZYP_997_的博客-CSDN博客

2.map详解

(1)map是STL的一个关联容器,它提供一对一的数据处理能力(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)

(2)map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的

(3)操作

插入数据:insert、数组插入

数据的查找:

  • 用count函数来判定关键字是否出现,其缺点是无法定位数据出现位置,由于map的特性,一对一的映射关系,就决定了count函数的返回值只有两个,要么是0,要么是1,出现的情况,当然是返回1了
  • 用find函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,它返回数据所在位置的迭代器,如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器

数据的清空与判空:

清空map中的数据可以用clear()函数,判定map中是否有数据可以用empty()函数,它返回true则说明是空map

(4)map 和 unordered_map 的区别?

  • 需要引入的头文件不同

       map: #include < map >
       unordered_map: #include < unordered_map >

  • 内部实现机理不同

        map: map内部实现了一个红黑树(红黑树是非严格平衡二叉搜索树,而AVL是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。map中的元素是按照二叉搜索树(又名二叉查找树、二叉排序树,特点就是左子树上所有节点的键值都小于根节点的键值,右子树所有节点的键值都大于根节点的键值)存储的,使用中序遍历可将键值按照从小到大遍历出来。
       unordered_map: unordered_map内部实现了一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的

  • 优缺点以及适用处

3.内存分配之alloca、calloc、malloc、free、realloc等

  (1)函数malloc()
        在内存的动态存储区中分配一块长度为size字节的连续区域,参数size为需要内存空间的长度,返回该区域的首地址.
    (2)函数calloc()
        与malloc相似,参数sizeOfElement为申请地址的单位元素长度,numElements为元素个数,即在内存中申请numElements*sizeOfElement字节大小的连续地址空间.
    (3)函数realloc()
        给一个已经分配了地址的指针重新分配空间,参数ptr为原有的空间地址,newsize是重新申请的地址长度. 

 区别:
    (1)函 数malloc不能初始化所分配的内存空间,而函数calloc能.如果由malloc()函数分配的内存空间原来没有被使用过,则其中的每一位可能都是 0;反之, 如果这部分内存曾经被分配过,则其中可能遗留有各种各样的数据.也就是说,使用malloc()函数的程序开始时(内存空间还没有被重新分配)能正常进 行,但经过一段时间(内存空间还已经被重新分配)可能会出现问题.
    (2)函数calloc() 会将所分配的内存空间中的每一位都初始化为零,也就是说,如果你是为字符类型或整数类型的元素分配内存,那么这些元素将保证会被初始化为0;如果你是为指针类型的元素分配内存,那么这些元素通常会被初始化为空指针;如果你为实型数据分配内存,则这些元素会被初始化为浮点型的零.
    (3)函数malloc向系统申请分配指定size个字节的内存空间.返回类型是 void*类型.void*表示未确定类型的指针.C,C++规定,void* 类型可以强制转换为任何其它类型的指针.
    (4)realloc 可以对给定的指针所指的空间进行扩大或者缩小,无论是扩张或是缩小,原有内存的中内容将保持不变.当然,对于缩小,则被缩小的那一部分的内容会丢失.realloc并不保证调整后的内存空间和原来的内存空间保持同一内存地址.相反,realloc返回的指针很可能指向一个新的地址.
    (5)realloc 是从堆上分配内存的.当扩大一块内存空间时,realloc()试图直接从堆上现存的数据后面的那些字节中获得附加的字节,如果能够满足,自然天下太平; 如果数据后面的字节不够,问题就出来了,那么就使用堆上第一个有足够大小的自由块,现存的数据然后就被拷贝至新的位置,而老块则放回到堆上.这句话传递的 一个重要的信息就是数据可能被移动.

4.计算机网络四层模型

Q1:TCP/IP 四层模型和 OSI 七层模型比较

 

Q2:四层结构的不同之处

 

 

5.为什么是四次挥手,不是三次?

  • 报文段1:主动关闭方向被动关闭方发送结束报文段。
  • 报文段2:被动关闭方发送结束报文段确认,此时主动关闭方数据已经传输完毕。
  • 报文段3:被动关闭方数据也发送完毕,发送结束报文段。
  • 报文段4:主动关闭方对结束报文段进行确认。

 观察四次挥手过程可见报文段3包含了报文段2中的确认值,因此三次挥手只能将报文段3和报文段2合并。但这样合并是有问题的。被动关闭方发送报文段2只是确认主动关闭方发来的结束报文段,但并不代表自身的数据已经传输完毕。即就是当断开连接的时候,一个方向的断开,只是说明该方向数据已传输完毕,而另一方向或许还有数据,所以要等到另一个方向数据也全部传输完成后,才能实现三次握手。但是这个时间不确定,因此会造成主动关闭方的结束报文段长时间未得到响应而进行超时重传等等。造成了不必要的资源浪费甚至更意想不到的问题

 参考:为什么是四次挥手不是三次挥手_judgejames的博客-CSDN博客_为什么是四次挥手不是三次

6.什么时候使用静态变量和静态函数

成员变量:当所有对象中的成员变量的数值相同时,此成员变量可以用static修饰
成员函数:当一个函数中没有调用静态变量时,此方法可以用static修饰;否则,此方法不能用static修饰

 7.多个类同时访问一个对象,怎么办?

用extern声明全局变量,只定义不赋值

 8.全局变量在使用过程中有没有遇到过什么问题?

①滥用全局变量会造成不必要的常量频繁使用

②会导致软件分层的不合理,全局变量相当于一条快捷通道,它容易使程序员模糊了“设备层”和“应用层”之间的边界,这在软件系统的构建初期的确效率很高,功能调试进度一日千里,但到了后期往往bug一堆,处处“补丁”

③由于软件的分层不合理,到了后期维护,哪怕仅是增加修改删除小功能,往往要从上到下掘地三尺地修改,涉及大多数模块,而原有的代码注释却忘了更新修改

④无意间的修改、命名冲突、并发问题、阻碍代码复用、干扰模块化

参考:为何不建议使用全局变量? - 知乎

 9.一个静态的对象,可以访问一个非静态的方法吗?

 静态成员函数不能访问非静态成员,这是因为静态函数属于类而不是属于整个对象,静态函数中的 member可能都没有分配内存。静态成员函数没有隐含的this自变量。所以,它就无法访问自己类的非静态成员。即静态成员属于类,不需要生成对象就存在了.而非静态需要生成对象才产生,所以静态成员不能直接访问

 10.类的构造函数和成员的构造函数的顺序

 父类的构造函数先于子类的构造函数执行。

在初始化子类之前需要通过构造函数初始化父类的成员变量。当实例化子类,子类要调用构造函数初始化成员变量,如果先执行了子类的构造函数,再执行父类的构造函数,父类成员字段的值会覆盖子类成员字段的值。但是我们想得到的是子类的属性值。所以为了解决数据冲突,父类的构造函数要先于子类的构造函数执行。

11.构造函数能抛异常吗?析构函数?

(1)构造函数中抛出异常,会导致析构函数不能被调用,但对象本身已申请到的内存资源会被系统释放。因为析构函数不能被调用,所以可能会造成内存泄露或系统资源未被释放。构造函数中可以抛出异常,但必须保证在构造函数抛出异常之前,把系统资源释放掉,防止内存泄露

(2)不要在析构函数中抛出异常!虽然C++并不禁止析构函数抛出异常,但这样会导致程序过早结束或出现不明确的行为。如果某个操作可能会抛出异常,class应提供一个普通函数(而非析构函数),来执行该操作。目的是给客户一个处理错误的机会。如果析构函数中异常非抛不可,那就用try catch来将异常吞下,但这样方法并不好,我们提倡有错早些报出来。

12.假设我发现有大量的close_wait状态,你觉得是出了什么问题呢?

在被动关闭连接情况下,在已经接收到FIN,但是还没有发送自己的FIN的时刻,连接处于CLOSE_WAIT状态。通常来讲,CLOSE_WAIT状态的持续时间应该很短。出现大量close_wait的现象,主要原因是某种情况下对方关闭了socket链接,但是我方忙与读或者写,没有关闭连接。代码需要判断socket,一旦读到0,断开连接,read返回负,检查一下errno,如果不是AGAIN,就断开连接。

13. Mysql的常用引擎?

数据库引擎是用于存储、处理和保护数据的核心服务。利用数据库引擎可控制访问权限并快速处理事务,从而满足企业内大多数需要处理大量数据的应用程序的要求

  • InnoDB:

InnoDB 的存储文件有两个,后缀名分别是 .frm 和 .idb,其中 .frm 是表的定义文件,而 idb 是数据文件。

InnoDB 中存在表锁和行锁,不过行锁是在命中索引的情况下才会起作用,外键约束。

InnoDB 支持事务,提供了对数据库ACID事务的支持,且支持四种隔离级别(读未提交、读已提交、可重复读、串行化),默认的为可重复读;而在 Oracle 数据库中,只支持串行化级别和读已提交这两种级别,其中默认的为读已提交级别。

  • Myisam :

Myisam 的存储文件有三个,后缀名分别是 .frm、.MYD、MYI,其中 .frm 是表的定义文件,.MYD 是数据文件,.MYI 是索引文件。

Myisam 只支持表锁,且不支持事务。Myisam 由于有单独的索引文件,在读取数据方面的性能很高 。

  • InnoDB 和 Myisam 都是用 B+Tree 来存储数据的

14.怎么理解可重复读?

可重复读指的是同一行在同一个事务下无论怎么读取都是同一个结果(除非自己把它改了);

不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致

幻读指的是在同一事务下,连续执行两次同样的SQL语句第二次的SQL语句可能返回之前不存在的行;

不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

15.C++空类的sizeof计算出来的大小是多少

空类的sizeof大小是1。为了区分空类定义出来的不同对象,空类同样可以被实例化。每个实例在内存中都有一个独一无二的地址,编译器给一个空类隐含的加一个字节,这样空类在实例化后在内存就可以得到独一无二的地址,所以空类所占的内存大小是1个字节。

附:空类作为基类的大小是多少

令无非静态数据成员、无虚函数的基类实际占0字节

16.菱形继承的解决办法

(1)两个派生类继承同一个基类,​又有某个类同时继承者两个派生类,​这种继承被称为菱形继承,或者钻石继承。

(2)菱形继承带来的主要问题是:子类继承两份相同的数据,导致资源浪费

(3)解决方法:要么用作用域,要么用虚继承

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值