【面试题】C++面试题整理——具身智能 / 自动驾驶 / 嵌入式 / 后台开发通用

目录

  • [一、C++ 基础 & 面向对象](#一、C++ 基础 & 面向对象)
    • [1. C 和 C++ 的核心区别是什么?](#1. C 和 C++ 的核心区别是什么?)
    • [2. 面向对象三大特性是什么,分别解释?](#2. 面向对象三大特性是什么,分别解释?)
    • [3. 重载、重写、隐藏分别是什么,有什么区别?](#3. 重载、重写、隐藏分别是什么,有什么区别?)
    • [4. struct 和 class 的区别是什么?](#4. struct 和 class 的区别是什么?)
    • [5. const 有哪些用法和作用?](#5. const 有哪些用法和作用?)
    • [6. static 有哪些用法和作用?](#6. static 有哪些用法和作用?)
    • [7. inline 内联函数是什么,有什么特点?](#7. inline 内联函数是什么,有什么特点?)
    • [8. explicit 关键字的作用是什么?](#8. explicit 关键字的作用是什么?)
    • [9. friend 友元函数/友元类的作用是什么?](#9. friend 友元函数/友元类的作用是什么?)
  • 二、构造、析构、拷贝、RAII
    • [1. 构造函数的作用和特点?](#1. 构造函数的作用和特点?)
    • [2. 析构函数的作用和特点?](#2. 析构函数的作用和特点?)
    • [3. 拷贝构造函数什么时候会被调用?](#3. 拷贝构造函数什么时候会被调用?)
    • [4. 浅拷贝与深拷贝是什么,区别是什么?](#4. 浅拷贝与深拷贝是什么,区别是什么?)
    • [5. 拷贝赋值与移动赋值的区别?](#5. 拷贝赋值与移动赋值的区别?)
    • [6. RAII 是什么,核心思想是什么?](#6. RAII 是什么,核心思想是什么?)
    • [7. 右值引用和移动语义的作用?](#7. 右值引用和移动语义的作用?)
  • 三、指针、引用、智能指针
    • [1. 指针和引用的区别是什么?](#1. 指针和引用的区别是什么?)
    • [2. 空指针、野指针、悬空指针分别是什么?](#2. 空指针、野指针、悬空指针分别是什么?)
    • [3. 指针常量和常量指针的区别?](#3. 指针常量和常量指针的区别?)
    • [4. C++ 有哪些智能指针?](#4. C++ 有哪些智能指针?)
    • [5. unique_ptr 的特点和使用场景?](#5. unique_ptr 的特点和使用场景?)
    • [6. shared_ptr 原理是什么,引用计数作用?](#6. shared_ptr 原理是什么,引用计数作用?)
    • [7. weak_ptr 作用是什么,解决什么问题?](#7. weak_ptr 作用是什么,解决什么问题?)
    • [8. 智能指针循环引用问题是什么,如何解决?](#8. 智能指针循环引用问题是什么,如何解决?)
  • 四、多态、虚函数、继承(超级高频)
    • [1. 多态是什么,分为哪两种,实现原理?](#1. 多态是什么,分为哪两种,实现原理?)
    • [2. 虚函数、虚表、虚指针分别是什么?](#2. 虚函数、虚表、虚指针分别是什么?)
    • [3. 纯虚函数和抽象类是什么?](#3. 纯虚函数和抽象类是什么?)
    • [4. 为什么析构函数需要定义为 virtual?](#4. 为什么析构函数需要定义为 virtual?)
    • [5. 构造函数可以是虚函数吗,为什么?](#5. 构造函数可以是虚函数吗,为什么?)
    • [6. public/protected/private 三种继承权限区别?](#6. public/protected/private 三种继承权限区别?)
    • [7. 菱形继承问题是什么,虚继承如何解决?](#7. 菱形继承问题是什么,虚继承如何解决?)
  • 五、内存管理(嵌入式/机器人必考)
    • [1. C++ 内存分区有哪几个?](#1. C++ 内存分区有哪几个?)
    • [2. 栈和堆的区别是什么?](#2. 栈和堆的区别是什么?)
    • [3. malloc/free 和 new/delete 区别?](#3. malloc/free 和 new/delete 区别?)
    • [4. new/delete 与 new[]/delete[] 区别?](#4. new/delete 与 new[]/delete[] 区别?)
    • [5. 内存泄漏是什么,如何避免?](#5. 内存泄漏是什么,如何避免?)
    • [6. 内存对齐是什么,为什么需要?](#6. 内存对齐是什么,为什么需要?)
    • [7. 野指针、悬空指针如何避免?](#7. 野指针、悬空指针如何避免?)
  • 六、C++11/14/17(必问现代C++)
    • [1. 右值引用、移动语义是什么?](#1. 右值引用、移动语义是什么?)
    • [2. 完美转发 std::forward 作用?](#2. 完美转发 std::forward 作用?)
    • [3. lambda 表达式是什么,有哪些捕获方式?](#3. lambda 表达式是什么,有哪些捕获方式?)
    • [4. constexpr 和 const 区别?](#4. constexpr 和 const 区别?)
    • [5. nullptr 和 NULL 区别?](#5. nullptr 和 NULL 区别?)
    • [6. auto 关键字作用与注意事项?](#6. auto 关键字作用与注意事项?)
    • [7. 范围 for 循环的原理是什么?](#7. 范围 for 循环的原理是什么?)
  • 七、多线程与并发(必问)
    • [1. 进程与线程的区别?](#1. 进程与线程的区别?)
    • [2. 互斥锁 mutex 作用是什么?](#2. 互斥锁 mutex 作用是什么?)
    • [3. 条件变量作用与使用场景?](#3. 条件变量作用与使用场景?)
    • [4. 死锁四个必要条件,如何避免?](#4. 死锁四个必要条件,如何避免?)
    • [5. 原子操作 atomic 作用?](#5. 原子操作 atomic 作用?)
    • [6. 线程安全问题是什么?](#6. 线程安全问题是什么?)
    • [7. 生产者消费者模型实现思路?](#7. 生产者消费者模型实现思路?)
  • 八、底层/嵌入式/机器人特化(必问)
    • [1. 大小端字节序是什么,如何判断?](#1. 大小端字节序是什么,如何判断?)
    • [2. volatile 关键字作用是什么?](#2. volatile 关键字作用是什么?)
    • [3. 函数调用栈帧大致过程?](#3. 函数调用栈帧大致过程?)
    • [4. 中断上下文为什么不能 sleep 和 mutex?](#4. 中断上下文为什么不能 sleep 和 mutex?)
    • [5. 如何写出低延迟代码?](#5. 如何写出低延迟代码?)
    • [6. 如何减少内存拷贝?](#6. 如何减少内存拷贝?)

一、C++ 基础 & 面向对象

1. C 和 C++ 的核心区别是什么?

C 是面向过程,关注步骤和流程;C++ 是面向对象 + 泛型编程,支持类、继承、多态、STL、智能指针等。

C 适合底层驱动、嵌入式;C++ 适合机器人、自动驾驶、后台、大型项目。

2. 面向对象三大特性是什么,分别解释?

  • 封装:把数据和方法打包,隐藏内部细节,只暴露接口,安全又好维护。
  • 继承:复用已有类的代码,扩展新功能,减少重复。
  • 多态:同一个接口,不同对象表现不同行为,灵活可扩展。

3. 重载、重写、隐藏分别是什么,有什么区别?

  • 重载:同一个类里,函数名相同,参数不同(个数/类型/顺序),和返回值无关。
  • 重写:子类重写父类的虚函数,函数名、参数完全一样,实现多态。
  • 隐藏:子类和父类函数同名,父类函数被隐藏,和是否虚函数无关。

4. struct 和 class 的区别是什么?

唯一区别:

  • struct 默认权限是 public
  • class 默认权限是 private
    其他功能几乎一样,struct 多用于简单数据结构,class 用于对象。

5. const 有哪些用法和作用?

  • 修饰变量:变量只读,不能修改。
  • 修饰指针:可以限定指针本身不能改,或指向内容不能改。
  • 修饰成员函数:函数内不能修改成员变量。
    作用:防止误改,增加安全性,编译器可优化。

6. static 有哪些用法和作用?

  • 全局 static:作用域仅限当前文件,外部不可见。
  • 局部 static:函数内变量,函数退出不销毁,值保留。
  • 类 static 成员:所有对象共享一份,不属于某个对象。
  • 类 static 函数:只能访问静态成员,没有 this 指针。

7. inline 内联函数是什么,有什么特点?

编译时把函数体直接展开到调用处,省去函数调用开销。

适合短小、高频函数。

特点:快,但代码会膨胀,不能有循环、递归、虚函数。

8. explicit 关键字的作用是什么?

禁止构造函数隐式类型转换

不加 explicit,单个参数的构造会被自动隐式转换,容易出bug;

加了只能显式调用,更安全。

9. friend 友元函数/友元类的作用是什么?

友元可以访问类的 private/protected 成员。

友元不是成员,是外部函数/类被授权访问。

优点:灵活;缺点:破坏封装,少用。


二、构造、析构、拷贝、RAII

1. 构造函数的作用和特点?

创建对象时自动调用,初始化成员变量。

  • 函数名和类名相同
  • 无返回值
  • 可以重载
  • 没写会自动生成默认构造

2. 析构函数的作用和特点?

对象销毁时自动调用,释放资源(内存、文件、锁等)。

  • 函数名是 ~类名
  • 无参无返回值
  • 不能重载
  • 有动态资源必须自己写

3. 拷贝构造函数什么时候会被调用?

用一个已存在的对象初始化同类型新对象时调用:

  • A a2 = a1;
  • A a2(a1);
  • 函数传值(对象作为参数)
  • 函数返回对象

4. 浅拷贝与深拷贝是什么,区别是什么?

  • 浅拷贝:只拷贝指针地址,两个对象共用同一块内存,会重复释放崩溃。
  • 深拷贝:重新开辟内存,拷贝数据,各自独立,安全。
    只要类有指针/动态资源,必须深拷贝。

5. 拷贝赋值与移动赋值的区别?

  • 拷贝赋值:赋值给已存在对象,拷贝数据,深拷贝。
  • 移动赋值:把临时对象(右值)的资源"偷过来",不拷贝,直接接管,更快。

6. RAII 是什么,核心思想是什么?

Resource Acquisition Is Initialization,资源获取即初始化。

利用对象生命周期管理资源:

  • 构造申请资源
  • 析构自动释放
    不用手动管理,避免泄漏。智能指针、锁都是 RAII。

7. 右值引用和移动语义的作用?

右值引用(&&)引用临时对象。

移动语义:把临时对象的资源直接"转移",不拷贝,大幅提升性能。

避免无谓拷贝,尤其大对象、容器。


三、指针、引用、智能指针

1. 指针和引用的区别是什么?

  • 指针可空、可改指向、多级指针;
  • 引用必须初始化、不能为空、绑定后不能改。
    引用更安全,指针更灵活。

2. 空指针、野指针、悬空指针分别是什么?

  • 空指针:nullptr,指向空,安全。
  • 野指针:未初始化,指向随机地址,极危险。
  • 悬空指针:指向的内存已释放,指针没置空。

3. 指针常量和常量指针的区别?

  • 常量指针(const int* p):指向的内容不能改,指针能改。
  • 指针常量(int* const p):指针不能改,内容能改。
    从右往左读:const 右边的不能改。

4. C++ 有哪些智能指针?

  • unique_ptr:独占,不能拷贝,性能最好。
  • shared_ptr:共享,引用计数。
  • weak_ptr:解决 shared_ptr 循环引用。

5. unique_ptr 的特点和使用场景?

独占对象,同一时间只有一个 owner。

不能拷贝,只能移动。

性能接近裸指针,优先用它。

6. shared_ptr 原理是什么,引用计数作用?

内部有引用计数 ,拷贝时+1,析构/赋值时-1。

计数为0才释放内存。

多个指针共享同一个对象。

7. weak_ptr 作用是什么,解决什么问题?

弱引用,不增加引用计数,只观察对象。

解决 shared_ptr 循环引用导致内存无法释放的问题。

8. 智能指针循环引用问题是什么,如何解决?

两个对象互相用 shared_ptr 持有对方,计数永远不为0,内存泄漏。

解决:把其中一个改成 weak_ptr。


四、多态、虚函数、继承(超级高频)

1. 多态是什么,分为哪两种,实现原理?

多态就是**"一个接口,多种实现"**,同样的调用,不同对象做不同事。

  • 分两种:
    1. 编译期多态(静态):重载、模板
    2. 运行期多态(动态):虚函数 + 继承 + 重写(面试重点)
  • 实现原理:
    基类指针/引用指向派生类对象,运行时通过虚表找到真正要调用的函数。

2. 虚函数、虚表、虚指针分别是什么?

  • 虚函数:前面带 virtual 的成员函数,用来实现多态。
  • 虚表(vtable):有虚函数的类,编译器会生成一张函数地址表,存所有虚函数地址。
  • 虚指针(vptr):对象里藏着一个指针,指向自己类的虚表。
    一句话:调用虚函数时,通过对象里的虚指针 -> 找到虚表 -> 找到正确函数。

3. 纯虚函数和抽象类是什么?

  • 纯虚函数:没有函数体,格式 virtual void func() = 0;
  • 抽象类:包含至少一个纯虚函数 的类。
    特点:不能创建对象,只能当接口用,强制子类必须实现它。

4. 为什么析构函数需要定义为 virtual?

如果基类指针指向派生类对象,析构函数不是虚函数,

销毁时只会调用基类析构,不会调用派生类析构 ,造成资源泄漏。

所以:基类析构一般都写成 virtual

5. 构造函数可以是虚函数吗,为什么?

不能!

  • 构造函数是用来创建对象的
  • 虚函数依赖虚指针,虚指针要等对象构造完才存在
  • 鸡和蛋的问题:还没构造好,就没有虚指针,不可能用虚函数
    所以构造函数不能是虚函数。

6. public/protected/private 三种继承权限区别?

记一句话:继承方式决定父类成员在子类里变成什么权限

  • public 继承:父类权限不变
  • protected 继承:父类 public → protected,其他不变
  • private 继承:父类所有成员 → private
    实际开发99%用 public 继承

7. 菱形继承问题是什么,虚继承如何解决?

菱形继承:B、C 继承 A,D 继承 B+C → D 里有两份 A,冲突、冗余。

虚继承:让 B、C 虚继承 A,D 里只保留一份 A,解决数据冗余和二义性。


五、内存管理(嵌入式/机器人必考)

1. C++ 内存分区有哪几个?

一共 5 个,非常好记:

  1. 栈:局部变量,自动释放
  2. 堆:new/malloc,手动释放
  3. 全局/静态区:全局变量、static
  4. 常量区:字符串、const 常量
  5. 代码区:程序代码

2. 栈和堆的区别是什么?

  • 栈:自动分配释放,速度快,空间小,连续内存
  • 堆:手动分配释放,速度慢,空间大,不连续
    栈像"储物柜",系统管;堆像"大仓库",自己管。

3. malloc/free 和 new/delete 区别?

  • malloc/free:C 语言函数,只分配/释放内存,不调用构造、析构
  • new/delete:C++ 运算符,分配内存 + 调用构造 ,释放 + 析构
    必须配对使用,不能混用。

4. new/delete 与 new[]/delete[] 区别?

  • new/delete:用于单个对象
  • new[]/delete[]:用于数组对象
    用 new[] 必须用 delete[],否则只析构一个对象,内存泄漏。

5. 内存泄漏是什么,如何避免?

内存泄漏:new 出来的内存,忘记 delete ,一直占着不释放。

后果:程序越跑越慢,最后崩。

避免方法:

  • 智能指针(unique_ptr/shared_ptr)
  • 用 RAII
  • 不裸指针乱飞

6. 内存对齐是什么,为什么需要?

内存对齐:数据在内存里放的地址,必须是固定大小的倍数(如4、8字节)。

为什么?

  • CPU 读内存是按块读的
  • 对齐后一次就能读完,不用拼数据,速度更快
  • 嵌入式/硬件必须对齐,否则直接报错

7. 野指针、悬空指针如何避免?

  • 野指针:指针一定要初始化,没指向就赋值 nullptr
  • 悬空指针:内存释放后,立刻把指针置空 nullptr
    口诀:初始化、释放置空、不用裸指针

六、C++11/14/17(必问现代C++)

1. 右值引用、移动语义是什么?

  • 右值引用 &&:专门引用临时对象(用完就丢的那种)
  • 移动语义:不拷贝数据,直接把临时对象的资源"抢过来"
    好处:快!不浪费内存拷贝

2. 完美转发 std::forward 作用?

在函数模板里,把参数原封不动、保持属性 转发给下一个函数。

左值还是左值,右值还是右值,不丢失属性,叫完美转发。

3. lambda 表达式是什么,有哪些捕获方式?

lambda 就是就地写的匿名函数

捕获方式:

  • \] 不捕获

  • \&\] 引用捕获

    简单、方便,写回调、线程、算法时超级常用。

4. constexpr 和 const 区别?

  • const:运行时常量,只读
  • constexpr:编译期就能算出值 ,性能更好
    能用 constexpr 就不用 const。

5. nullptr 和 NULL 区别?

  • NULL 本质是 0,容易被当成整数
  • nullptr 是真正的空指针,类型安全
    C++11 以后一律用 nullptr

6. auto 关键字作用与注意事项?

auto:让编译器自动推导类型 ,代码简洁。

注意:

  • 不能用于函数参数
  • 不能用于数组
  • 不要滥用,否则可读性差

7. 范围 for 循环的原理是什么?

底层就是迭代器:

自动调用 begin()end(),遍历每个元素。

写法简单:for(auto x : 容器)

注意:想修改元素用 for(auto& x : ...)


七、多线程与并发(必问)

1. 进程与线程的区别?

  • 进程:资源分配的基本单位,有独立内存空间,进程间不共享,切换开销大。
  • 线程:调度执行的基本单位,共享进程的内存(堆、全局变量),只独有栈,切换快。
    一句话:进程是房子,线程是房子里的人;人共享房子,但各自有小房间。

2. 互斥锁 mutex 作用是什么?

多个线程同时修改共享数据时,会出现混乱。

mutex 保证同一时间只有一个线程进入临界区 ,避免竞争。

作用:保护共享资源,保证原子性

3. 条件变量作用与使用场景?

条件变量用来让线程等待某个条件成立 ,不忙轮询。

场景:生产者消费者------队列空时消费者等,队列满时生产者等。

必须配合 mutex 使用:先加锁,再 wait,wait 会自动释放锁

4. 死锁四个必要条件,如何避免?

四个条件缺一不可:

  1. 互斥(资源独占)
  2. 持有并等待(拿着锁等别的锁)
  3. 不可抢占(锁不能被抢走)
  4. 循环等待(A等B,B等A)

避免:

  • 按固定顺序加锁
  • 避免持有锁时等待其他锁
  • 加锁超时
  • 破坏循环等待

5. 原子操作 atomic 作用?

简单操作(+1、赋值)本来看似一步,底层可能分多步,多线程会错乱。

atomic 让这些操作CPU 指令级原子性 ,不可分割,不用锁也线程安全。

优点:无锁、快、轻量

6. 线程安全问题是什么?

多个线程同时访问共享数据,读写交错,导致结果错误、不可预测。

原因:竞争条件 + 非原子操作

解决:锁、原子变量、避免共享。

7. 生产者消费者模型实现思路?

  1. 共享队列(缓冲区)
  2. 互斥锁:保护队列
  3. 两个条件变量:队列不为空、队列不满
    流程:
  • 生产者:加锁 → 满则等 → 放数据 → 通知消费者 → 解锁
  • 消费者:加锁 → 空则等 → 取数据 → 通知生产者 → 解锁

八、底层/嵌入式/机器人特化(必问)

1. 大小端字节序是什么,如何判断?

  • 大端:高字节存低地址(人类书写顺序)
  • 小端:低字节存低地址(x86/ARM 默认)

判断方法:

把 int 数 0x11223344 转成 char*,看第一个字节是 0x11 还是 0x44。

2. volatile 关键字作用是什么?

告诉编译器:这个变量可能随时被外部改变(硬件、中断、其他线程),不要优化它,每次都从内存读,别用寄存器缓存。

场景:硬件寄存器、中断变量、多线程共享。

3. 函数调用栈帧大致过程?

  1. 调用方把参数压栈
  2. 压入返回地址
  3. 进入被调用函数,保存旧栈帧ebp
  4. 分配局部变量空间
  5. 执行函数
  6. 恢复栈帧,返回

形象理解:栈帧就是函数的"临时小本子",调用时翻开,结束撕掉。

4. 中断上下文为什么不能 sleep 和 mutex?

  • 中断不属于任何进程/线程,没有调度信息,一睡就醒不来,系统崩溃。
  • mutex 可能阻塞等待,中断里不能阻塞、不能调度
    中断只能用:自旋锁、关中断、信号量(不阻塞版)。

5. 如何写出低延迟代码?

  • 少用锁,用无锁、原子
  • 避免内存拷贝
  • 避免动态分配(malloc/new)
  • 线程绑核,避免切换
  • 减少中断、软中断
  • 临界区极短
  • 用实时调度策略

6. 如何减少内存拷贝?

  • 用引用 &,不用值传递
  • 用移动语义 move
  • 用指针/索引代替拷贝
  • mmap、零拷贝
  • 大容器直接复用,不创建新的
  • 用 shared_ptr 代替深拷贝
相关推荐
ol木子李lo2 小时前
Qt6 替代废弃 QMediaPlaylist 的解决方案
c语言·c++·vscode·qt·个人开发·visual studio·qt6.3
雨浓YN2 小时前
WPF MVVM 模式(调Prism库)项目创建笔记 —— 包含C++/CLI OpenCV互操作
c++·笔记·wpf
清辞8532 小时前
【Day4】C++竞赛每日练习
数据结构·c++·算法
‎ദ്ദിᵔ.˛.ᵔ₎2 小时前
C++ 继承
开发语言·c++
史迪仔01122 小时前
[QML] Popup 与 Dialog
开发语言·前端·javascript·c++·qt
John.Lewis2 小时前
C++加餐课-stack_queue:计算器-逆波兰表达式
开发语言·c++
SilentSamsara2 小时前
Linux 管道与重定向:命令行精髓的结构性解析
linux·运维·服务器·c++·云原生
zjeweler10 小时前
“网安+护网”终极300多问题面试笔记-3共3-综合题型(最多)
笔记·网络安全·面试·职场和发展·护网行动
lclin_202010 小时前
VS2010兼容|C++系统全能监控工具(彩色界面+日志带单位+完整版)
c++·windows·系统监控·vs2010·编程实战