深圳帝迈生物 qt
简历上写的一定要熟悉,面试官会根据简历问很多东西。面试制造业,面试官不懂网络编程,所以web服务器项目问的都是优化部分。
多态
回答的太简单,一下子想不起来。
重载:静态多态,编译时绑定
重写:动态多态,运行时绑定
动态多态条件:
通过基类指针或引用指向对象,并调用虚函数。根据对象的实际类型,调用对应的虚函数。
使用虚表和虚表指针实现。 当使用指针或引用调用虚函数时,指针指向对象的虚表指针,虚表指针指向基类或派生类的虚表,遍历虚表,找到对应的虚函数。
虚表、虚表指针
类——虚表,对象——虚表指针
位置:
虚表——.rodata段(只读数据区,常量也可能存放在这里)
智能指针用过吗?作用?哪几种?
回答:用过,但不多(不好,可以直接回答用过;问项目中有没有用过)
作用:
自动内存管理,避免内存泄漏。使用RAII(资源获取即初始化)。
防止空悬指针,智能指针初始化会进行空指针检查,避免访问空指针。
提高代码可读性和维护性:自动管理内存,减少错误;语义清晰(共享、独占),更好表达程序的意图
普通指针的问题?
相比智能指针:
内存泄漏,忘记释放
野指针:释放后忘记置空,再次访问,出现问题
未初始化
内存重复释放
普通指针本身:
指针越界
c++容器中存放指针,容器销毁后,指针内存会自动释放吗?
普通指针
容器中存放了指针,当容器被销毁时,容器会自动删除其元素,但是这并不包括指针所指向的内存。也就是说,容器销毁后,指针所指向的内存并不会被自动释放。
如果你在容器中存放了指针,并且你希望在容器销毁时自动释放指针所指向的内存,你需要在容器销毁之前手动释放这些内存。
释放指针的内存之前,要确保这些指针所指向的内存不再被使用,否则可能会导致未定义的行为。如果想避免手动管理内存,你可以考虑使用智能指针,如std::shared_ptr
或std::unique_ptr
,它们会在不再需要时自动释放内存
智能指针
容器中存放了智能指针,当容器被销毁时,智能指针也会被自动销毁,同时它们所指向的内存也会被自动释放。
智能指针(如std::shared_ptr
和std::unique_ptr
)的设计目的就是为了自动管理内存。当智能指针的生命周期结束时(例如,当它们离开其定义的范围,或者它们所在的容器被销毁时),它们会自动删除其所指向的对象。
std::shared_ptr
允许多个指针指向同一个对象,当最后一个std::shared_ptr
被销毁时,它会删除所指向的对象。而std::unique_ptr
则保证只有一个指针指向对象,当这个std::unique_ptr
被销毁时,它会删除所指向的对象。因此,需要根据你的具体需求来选择使用哪一种智能指针。
容器销毁,会发生什么?
-
容器的析构函数被调用:这是在容器对象的生命周期结束时自动发生的,例如当容器对象离开其定义的范围,或者如果它是一个动态分配的对象,当你使用
delete
操作符时。 -
容器的所有元素被销毁:这意味着每个元素的析构函数都会被调用。对于基本类型(如
int
,double
等),这通常没有什么特别的效果。但是,对于类类型的对象,这可能会有重要的副作用,因为类的析构函数可以执行任何操作。 -
释放内存:容器会释放用于存储其元素的内存。这是通过调用适当的内存释放函数(如
delete
或delete[]
)来完成的。
请注意,容器销毁其元素并不意味着它会销毁元素所指向的对象(如果元素是指针)。这意味着如果你在容器中存储了指向动态分配内存的指针,你需要在容器销毁之前手动释放这些内存,否则可能会导致内存泄漏。
c++容器拷贝,容器中存放的数据是深拷贝还是贝?
基本数据类型(int,double):容器拷贝操作会创建元素的副本,可视为深拷贝
指针或引用:只会拷贝指针本身,浅拷贝,不会拷贝指针所指向的对象;所有拷贝的指针指向同一块空间(可以使用智能指针,帮助实现内存管理)
类对象:深拷贝,但如果类中有指针成员,默认浅拷贝指针,如果向实现指针的深拷贝,需要手动实现拷贝构造函数。
拷贝构造函数注意点?
有指针成员时,注意要实现深拷贝还是浅拷贝;
参数是常量引用:
避免无线递归:避免调用拷贝构造函数时需要复制参数,递归调用拷贝构造函数
保护数据
提高效率
c++11新特性
智能指针
右值
匿名函数
范围for循环
自动类型推导:auto()根据值推导;decltype()根据表达式推导,但不计算表达式
nullptr代替NULL
vector使用注意点
在堆中分配空间
扩容后,所有迭代器都失效; 怎样扩容的?
释放空间:clear()清空元素,size=0; shrink_to_fit()释放多余内存,使容器实际占用空间等于有效元素占用空间
resize() 和 reserve()
迭代器使用注意点
迭代器不是指针,是类模板,封装了指针。模拟了指针的一些功能,重载了指针的一些操作符,-->、++、--等。
迭代器返回的是对象引用而不是对象的值
注意迭代器的有效性,不要使用无效迭代器
迭代器失效场景
序列式容器,vector:增删会使后面 迭代器都失效;扩容,所有迭代器都失效
list:增删不会对其余的迭代器造成影响
map和set底层使红黑树,删除元素,对后面的迭代器没有影响
项目
1 定时器优化
说的很烂,需要整理
定时器的变化使很频繁的,使用小根堆存储定时器,堆顶为过期时间最小的,添加和修改定时器的时间为O(logn),链表为O(n)
删除:堆:O(logn) 链表:O(1)直接删除表头结点
2 零拷贝
传统文件传输:read+write两次系统调用,磁盘-内核缓冲区-用户缓冲区-socket缓冲区-网卡,四次拷贝
零拷贝:sendfile一次系统调用,磁盘-内核缓冲区(PageCache)-网卡,两次拷贝,全程没有使用cpu搬运数据,全都使用DMA传输。可把文件传输性能提高一倍以上。
但零拷贝技术使用了PageCache,PageCache会缓存最近访问的数据。传输大文件不能使用零拷贝,否则PageCache被大文件占据,导致热点文件无法使用PageCache,缓存命中率下降。
设定一个阈值,大文件传输使用异步IO(read之后直接返回,读完之后再提醒cpu;避开PageCache,也叫直接IO)
3 优化后测试过吗?怎样检测的?
没有,乱扯
4 线程同步
线程池的线程使独立的吗?
怎样实现线程同步?
你用的是哪个? 互斥锁、条件变量(错了,其实是信号量)
为什么两个一起使用?
互斥锁:保证互斥访问
信号量:实现线程同步
锁使用注意点
5 设计模式
单例模式,类必须保证只有一个实例存在。
- 懒汉式:指全局的单例实例在第一次被使用时构建。
- 饿汉式:全局的单例实例在类装载(ClassLoader)时构建。(饿汉式单例性能优于懒汉式单例)
懒汉式在多线程中是线程不安全的,而饿汉式是不存在多线程安全问题的
懒汉:私有构造函数,使用类的私有静态指针指向唯一实例,使用一个公有方法获取该实例
饿汉:线程安全,在程序运行之初就创建了对象,问题是创建的时间和获取的时间前后顺序不能保证
优点:
只有一个实例,减少内存开销;提供对唯一实例的受控制的访问
缺点:
单例模式扩展比较困难;
单例类职责过重,违背单一职责原则
使用场景:
创建对象消耗资源过多,如IO与数据库连接等
简历挖坑:静态库和动态库制作
makefile
怎样远程调试?gdb
- 编译:gcc -g test.c -o test -g:在可执行文件中加入源代码信息
- 启动:gdb test
- list 显示源码 set listsize 设置显示的行数
- 设置断点:break 行号 break 函数名
- 查看断点信息:Info break delete 断点编号
- 执行:run
- 单步执行:next step(进入函数) continue
- 查看变量:print 变量名
- 退出:q
TCP包头
拥塞控制怎么实现?
滑动窗口
先临三维
匿名函数细节 值传递拷贝操作什么时候做???表达式创建时,还是调用时?不会
值传递:创建时
引用传递:使用时