友元函数能不能是虚函数: 友元函数不属于类的成员函数,它独立于类存在,因此不存在是否为虚函数的概念。友元函数主要用于突破类的封装性,使外部函数能访问类的私有和保护成员,它与类的继承和多态无关。 TCP三握四挥: TCP连接建立过程(三次握手): 客户端发送带有SYN标志的数据包给服务器,进入SYN_SENT状态。 服务器接收到SYN后回复带有SYN+ACK标志的数据包,进入SYN_RECEIVED状态。 客户端收到服务器的SYN+ACK后,再发送一个带有ACK标志的数据包作为确认,此时客户端和服务端都进入ESTABLISHED状态,完成连接建立。 TCP连接关闭过程(四次挥手): 主动关闭方(例如客户端)发送FIN标志的数据包给对方,进入FIN_WAIT_1状态。 服务端接收到FIN后,回复一个带有ACK标志的数据包,进入CLOSE_WAIT状态,此时客户端进入FIN_WAIT_2状态。 服务端准备好关闭连接时,发送自己的FIN标志的数据包,进入LAST_ACK状态。 客户端收到服务端的FIN后,再次回复一个带有ACK标志的数据包,进入TIME_WAIT状态,等待一段时间确保最后一个ACK已被服务端接收后彻底关闭连接;服务端收到最后一个ACK后关闭连接。 数据结构封装: 在编程中,数据结构的封装是指将数据结构(如数组、链表、树、图等)以及在其上进行操作的方法一起包装在类或结构体中,形成一个独立且易于使用的单元。通过封装,可以隐藏实现细节,提供一致和安全的接口,方便代码维护和重用。 例如,在C++中封装一个简单的动态数组:
Cpp
template < typename T>
class MyVector {
private : T* data; int size; int capacity; public : MyVector ( int initial_capacity = 10 ) ; ~ MyVector ( ) ; MyVector ( const MyVector& other) ; MyVector& operator = ( const MyVector& other) ; void push_back ( T value ) ; void pop_back ( ) ; T& at ( int index) ; const T& at ( int index) const ; int getSize ( ) const { return size; } int getCapacity ( ) const { return capacity; }
private : void resize ( int new_capacity) ;
} ;
map与unordered_map的区别及使用场景:std::map: 底层通常采用红黑树(RBTree)实现,保证键值对按键的升序排列。 插入、删除和查找的时间复杂度均为O(log n),其中n是元素数量。 如果需要有序遍历或者基于键的排序操作,map是一个很好的选择。 示例使用场景:电话簿(按姓名排序)、日志记录(按时间戳排序)等。 std::unordered_map: 底层采用哈希表(Hash Table)实现,不保证内部顺序。 查找、插入和删除平均时间复杂度为O(1),但最坏情况下可能是O(n)(当哈希冲突严重时)。 若仅需高效查找而不关心顺序,unordered_map更优。 示例使用场景:缓存系统、关键词索引等无需排序的应用。 总结: 当需要键值对保持有序性时,应选用std::map。 对于快速查找和不需要维持顺序的场景,优先考虑使用std::unordered_map以获取更好的平均性能。同时,unordered_map对于内存要求可能更低,因为其存储结构更为紧凑。然而要注意的是,由于哈希表的特性,当插入大量数据时,合理的负载因子和良好的哈希函数对于性能至关重要。