百色市网站建设_网站建设公司_测试工程师_seo优化
2026/1/20 16:32:08 网站建设 项目流程

1.vector 和 list 的区别?

  • vector 是内存连续的线性结构,支持随机访问,插入/删除(非末尾)效率低(需移动元素)。

  • list 是内存不连续的链表结构,不支持随机访问,但任意位置插入/删除效率高(O(1))。

  • 遍历时 vector 因内存连续(缓存友好)性能更高,list 易导致 Cache Miss。


2.进程和线程的区别?

  • 进程是资源分配的基本单位,线程是CPU调度的基本单位。

  • 进程间内存隔离,线程共享堆、全局变量、代码段,但各有独立栈和寄存器上下文。

  • 线程切换开销小(仅保存寄存器),进程切换需更新页表等,开销大。

  • 进程间通信需 IPC(管道、消息队列等),线程可直接通过共享内存通信。

  • 一个线程崩溃可能导致整个进程崩溃,进程间则相互独立。


3.智能指针和循环引用?

  • 智能指针是封装原生指针的栈对象,指向堆内存,内部含对象指针控制块指针(含引用计数等)。

  • 循环引用:如shared_ptr<A>shared_ptr<B>相互指向,导致引用计数永不为0,内存泄漏。

  • 解决:用weak_ptr替代一方,避免增加引用计数。


4.智能指针的两个区域

  • 对象区域:指向实际堆内存资源。

  • 控制块区域:指向堆中的控制块,包含强引用计数、弱引用计数、删除器等。


5.信号量

  • 本质是原子计数器,用于控制访问共享资源的线程数量,达到值时阻塞后续线程。


6.互斥锁、读写锁、自旋锁

  • 互斥锁:线程未获锁时被挂起(休眠)。

  • 读写锁:读锁可共享,写锁独占。

  • 自旋锁:线程未获锁时循环尝试(忙等),不挂起,适合短时间等待。


7.TCP 三次握手

  • 过程:SYN → SYN-ACK → ACK。

  • 服务端:收到 SYN 放入半连接队列,收到 ACK 后移入全连接队列


8.map 和 unordered_map 的区别

  • map:基于红黑树,有序,查找 O(logN)。

  • unordered_map:基于哈希表,平均 O(1),无序,需处理哈希冲突。


9.继承和多态

  • 继承:实现代码复用。

  • 多态:动态多态通过虚函数重写实现,统一接口;动态绑定在运行时确定调用函数。


10.内存空间布局

  • 自低地址到高地址:

    1. 代码区、常量区、静态区(BSS、Data)

    2. 堆区(向上增长)

    3. 共享库映射区

    4. 栈区(向下增长)

    5. 内核空间

  • 堆和栈大小动态变化,中间有共享库区。


11.C++ 内存分布:栈区 vs 堆区

  • 栈区:局部变量、函数参数、返回地址(自动管理)。

  • 堆区:malloc/new动态分配,手动管理生命周期。


12.C++ 从源程序到可执行文件的过程

  1. 预处理:处理宏、头文件、条件编译等(.cpp.i)。

  2. 编译:将源代码转为汇编(.i.s)。

  3. 汇编:将汇编转为机器码(.s.o)。

  4. 链接:合并多个目标文件及库,生成可执行文件。


13.多线程同步方式

  • 互斥锁、读写锁、自旋锁、信号量、条件变量、屏障等。


14.sizeof在编译期还是运行期确定?

  • 固定大小类型(如基本类型、结构体)在编译期确定。

  • 可变长度数组(C99)​ 在运行时计算,但 C++ 不支持变长数组。


15.函数重载机制及确定时机

  • 重载依赖函数名、参数类型/数量/顺序,在编译期确定(名字改编)。

  • 虚函数重写(多态)在运行期通过虚函数表确定。


16.常量指针和指针常量

  • 常量指针const int* pint const* p,指针指向的内容不可变。

  • 指针常量int* const p,指针本身(指向)不可变。


17.vector 原理及扩容

  • 内部维护三个指针:startfinishend_of_storage

  • 当容量不足时,按一定比例(如 1.5 或 2 倍)重新分配内存,复制原数据到新空间。


18.引用和指针的区别

  • 引用必须初始化且不能为空,指针可以为空。

  • 引用不能改变指向,指针可以。

  • 引用是别名,指针是独立变量存储地址。


19.auto遍历容器

  • 传统遍历:for (auto it = vec.begin(); it != vec.end(); ++it)需手动*it解引用。

  • 范围 for 循环:for (auto& val : vec)自动解引用。


20.static_castdynamic_cast

  • static_cast:编译期转换,用于相关类型(如数值类型、基类转派生类),不进行运行时检查。

  • dynamic_cast:运行期检查,用于多态类型(需虚函数),安全向下转换,失败返回nullptr


21.inline#define

  • inline:编译期展开,有类型检查,可调试。

  • #define:预处理文本替换,无类型检查,难调试。


22.newmalloc的区别

  • new是运算符,自动计算大小,调用构造函数,返回类型指针。

  • malloc是函数,需手动指定字节数,不调用构造函数,返回void*


23.如何防止头文件被多次包含?

  1. #pragma once(非标准但广泛支持)。

  2. 条件编译

    #ifndef HEADER_NAME #define HEADER_NAME // 头文件内容 #endif

24.父子进程匿名管道读写安全

  • 管道是内核 FIFO 队列,保证读写顺序(先写先读)。

  • 读写原子性:单次写操作 ≤ 4KB 是原子的。

  • 无数据时读阻塞,满时写阻塞。


25.类中能调用同类对象的私有方法吗?

  • 可以,同类的不同对象可访问彼此的私有成员(封装是针对类而非对象)。


26.C++ 内存管理及常见问题

  • 分区:栈、堆、静态/全局、常量、代码区。

  • 管理方式:new/deletemalloc/free、智能指针。

  • 常见问题:

    • 内存泄漏

    • 野指针/悬垂指针

    • 重复释放

    • 内存碎片


27.堆栈内存常见问题

  • :溢出(递归过深、局部变量过大)。

    • 内存泄漏

    • 越界访问

    • 使用已释放内存

    • 碎片化


28.派生类中调用父类同名方法

class Base { public: void func() {} }; class Derived : public Base { public: void func() { Base::func(); // 显式调用父类版本 } };

29.派生类中定义父类指针

class Base { /* ... */ }; class Derived : public Base { /* ... */ }; Base* ptr = new Derived(); // 父类指针指向派生类对象

30.volatile的作用

  • 防止编译器优化对变量的读写(如多线程、硬件寄存器访问),确保每次访问都从内存读取。


31.僵尸进程和孤儿进程

  • 僵尸进程:子进程结束但父进程未回收(wait/waitpid),占用进程表项。

  • 孤儿进程:父进程先结束,子进程被 init/systemd 进程(PID=1)接管并回收。

  • 危害:僵尸进程过多导致进程表满,孤儿进程无害(会被系统回收)。


需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询