当前位置: 首页 > news >正文

C++ 是技术面试中的高频考察测点(基础知识)

C++ 是技术面试中的高频考察测点,涉及语法特性、内存管理、面向对象、STL 等多个领域。以下整理了常见面试题及核心要点,帮助系统梳理知识点:

一、基础语法与关键字

1. const 关键字的用法
  • 修饰变量:变量只读,初始化后不可修改(const int a = 5;)。
  • 修饰指针
    • const int* p:指针指向的内容不可修改(*p 只读)。
    • int* const p:指针本身不可修改(p 只读)。
    • const int* const p:指针及其指向的内容均不可修改。
  • 修饰函数参数:防止参数被意外修改(void func(const int& x)),常用于引用传递避免拷贝。
  • 修饰类成员函数:函数不可修改类的非静态成员变量(void print() const),常搭配 mutable 关键字突破限制。
2. 指针与引用的区别
特性指针引用
定义存储地址的变量(int* p = &a;变量的别名(int& r = a;
初始化可空(int* p = nullptr;必须初始化且不可空
指向修改可重新指向其他变量(p = &b;一旦绑定,无法更改指向
多级形式支持多级指针(int**p无多级引用
sizeof 结果地址长度(如 64 位系统为 8 字节)被引用变量的大小
操作需解引用(*p = 5;直接使用(r = 5;
3. static 关键字的作用
  • 修饰局部变量:延长生命周期至程序结束(仅初始化一次),作用域仍为函数内。
    void func() {static int count = 0; // 仅初始化一次count++; 
    }
    
  • 修饰全局变量/函数:限制作用域为当前文件,避免多文件编译冲突。
  • 修饰类成员
    • 成员变量:属于类而非对象,需在类外初始化(int A::count = 0;)。
    • 成员函数:无 this 指针,只能访问静态成员,可通过类名直接调用(A::func())。
4. 函数重载(Overload)与重写(Override)的区别
  • 重载:同一作用域内,函数名相同,参数列表(类型/个数/顺序)不同,与返回值无关。
    void print(int a) {}
    void print(string s) {} // 重载
    
  • 重写:派生类覆盖基类的虚函数,函数名、参数列表、返回值必须完全一致(协变返回类型除外),基类函数需加 virtual
    class Base {
    public:virtual void func() {}
    };
    class Derived : public Base {
    public:void func() override {} // 重写
    };
    
5. inline 内联函数的特点
  • 编译期替换:编译器将函数体嵌入调用处,减少函数调用开销(避免栈帧创建/销毁)。
  • 适用场景:短小函数(如getter/setter),长函数会导致代码膨胀。
  • 与宏的区别:内联函数有类型检查和作用域限制,宏仅为文本替换(无语法检查)。

二、面向对象(OOP)

1. 封装、继承、多态的概念
  • 封装:将数据(成员变量)和操作(成员函数)捆绑,通过 public/private/protected 控制访问,隐藏实现细节。
  • 继承:派生类复用基类的属性和方法,支持代码复用与扩展(如 class Derived : public Base)。
  • 多态:同一接口(基类指针/引用)调用不同派生类的实现,需通过虚函数实现动态绑定(运行时确定调用版本)。
2. 虚函数与纯虚函数
  • 虚函数:基类中用 virtual 修饰的函数,允许派生类重写,实现多态。
    virtual void func() { /* 基类实现 */ }
    
  • 纯虚函数:基类中声明但不实现的函数(virtual void func() = 0;),包含纯虚函数的类为抽象类,无法实例化,派生类必须实现纯虚函数才能实例化。
3. 虚析构函数的作用
  • 当基类指针指向派生类对象时,若基类析构函数非虚函数,删除指针时仅调用基类析构函数,导致派生类资源泄漏。
  • 解决:将基类析构函数声明为虚函数,确保析构时先调用派生类析构函数,再调用基类析构函数。
    class Base {
    public:virtual ~Base() { /* 基类清理 */ }
    };
    
4. 菱形继承问题及解决
  • 问题:派生类间接继承同一基类多次(如 A→BA→CD 继承 BC),导致 D 包含 A 的多份数据,访问时歧义。
  • 解决:虚继承(class B : virtual public A),确保基类 A 在派生类中仅存在一份实例。

三、内存管理

1. new/deletemalloc/free 的区别
特性new/deletemalloc/free
类型运算符标准库函数
类型检查自动匹配类型,返回对应指针返回 void*,需手动强转
构造/析构自动调用构造函数/析构函数仅分配/释放内存,不处理对象生命周期
失败处理抛出 bad_alloc 异常返回 NULL
重载可重载 operator new/delete不可重载
2. 堆(Heap)与栈(Stack)的区别
  • :由编译器自动管理,存储局部变量、函数参数、返回地址等,大小固定(通常几 MB),操作速度快,遵循“先进后出”。
  • :由程序员手动管理(new/malloc 分配,delete/free 释放),大小动态(可达 GB 级),操作速度慢,易产生内存碎片。
3. 智能指针(C++11)
  • unique_ptr:独占所有权,不可复制(仅可移动),适用于单一所有者场景。
    unique_ptr<int> p(new int(5));
    unique_ptr<int> p2 = move(p); // 转移所有权
    
  • shared_ptr:共享所有权,通过引用计数管理,计数为 0 时自动释放内存,需注意循环引用问题。
  • weak_ptr:不增加引用计数,用于观察 shared_ptr 管理的对象,解决循环引用(通过 lock() 获取 shared_ptr)。
4. 内存泄漏的常见原因
  • 动态分配的内存未释放(new 后未 deletemalloc 后未 free)。
  • 指针被意外修改(如野指针、悬挂指针)。
  • 容器或智能指针使用不当(如 shared_ptr 循环引用)。
  • 检测工具:Valgrind(Linux)、AddressSanitizer、Visual Studio 内存诊断。

四、STL(标准模板库)

1. 常见容器的底层实现
容器底层实现特点
vector动态数组连续内存,支持随机访问,尾部插入/删除高效
list双向链表非连续内存,任意位置插入/删除高效,无随机访问
deque分段连续内存(双端队列)头部/尾部操作高效,支持随机访问
map/set红黑树(自平衡BST)按键有序,插入/删除/查找复杂度 O(log n)
unordered_map/set哈希表无序,平均复杂度 O(1),最坏 O(n)
2. vector 迭代器失效场景
  • 插入元素:若触发扩容(重新分配内存),所有迭代器失效;未扩容时,插入位置及之后的迭代器失效。
  • 删除元素:删除位置及之后的迭代器失效,可通过返回值更新迭代器(it = vec.erase(it))。
3. mapunordered_map 的区别
  • 底层结构map 基于红黑树,unordered_map 基于哈希表。
  • 顺序map 按键升序排列,unordered_map 无序。
  • 性能unordered_map 平均查找更快(O(1)),但内存开销大;map 在频繁插入删除时更稳定。

五、C++11 及以上新特性

1. 移动语义与完美转发
  • 移动语义:通过右值引用(&&)转移资源所有权,避免不必要的拷贝(如 vector 扩容时的元素移动)。
  • 完美转发:通过 std::forward 保持参数的左值/右值属性,用于模板函数传递参数。
2. Lambda 表达式
  • 匿名函数,语法:[捕获列表](参数列表) -> 返回类型 { 函数体 }
    auto add = [](int a, int b) { return a + b; };
    
3. 其他特性
  • 范围 for 循环:for (auto& x : container) { ... }
  • 线程库:std::thread 支持多线程编程。
  • 原子操作:std::atomic 实现无锁同步。

六、总结

C++ 面试注重基础语法细节、内存管理能力、面向对象设计及 STL 应用。除理论知识外,需结合编程题练习(如链表操作、排序算法、动态规划等),理解时间/空间复杂度优化,才能在面试中应对自如。

http://www.lryc.cn/news/624313.html

相关文章:

  • 【数据库】Navicat 导入 Excel 数据乱码问题的解决方法
  • Laravel中如何使用php-casbin
  • Effective C++ 条款48:认识模板元编程
  • ARM 架构简明教程学习笔记
  • 23.CNN系列网络思考
  • 科伦博泰:商业化引爆点已至,冲向Biopharma的“最后一公里”
  • 基于C语言实现的HRV分析方法 —— 与Kubios和MATLAB对比
  • C++11列表初始化 {}
  • 【数据可视化-92】使用 Pyecharts 绘制乡镇街道级地图:以安徽省黄山市休宁县为例(我的老家)
  • 【数据结构】深入理解双向链表:结构、实现与对比分析
  • 后台管理系统-6-vue3之mockjs模拟和axios请求数据
  • 国产!全志T113-i 双核Cortex-A7@1.2GHz 工业开发板—ARM + DSP、RISC-V核间通信开发案例
  • 算法魅力-BFS解决多源最短路
  • go语言条件语if …else语句
  • Apache Shiro550 漏洞(CVE-2016-4437):原理剖析与实战 SOP
  • 检测手绘图中不规则曲线交点的方法和一般规则线条交点的方法
  • Alibaba Cloud Linux 3 在 Apple M 芯片 Mac 的 VMware Fusion 上部署的完整密码重置教程(二)
  • SAP 简单的AMDP demo 练习使用
  • Midjourney绘画创作入门操作创作(在线教育背景系列)
  • 广州曼顿智能断路器:让用电更聪明,生活更安心!
  • SSM-组件的批量扫描
  • Linux中基于Centos7使用lamp架构搭建个人论坛(wordpress)
  • 双通道审核智能合约更新路径:基于区块链与AI融合的编程范式分析
  • 静态网站与动态网站的区别
  • 笔试——Day42
  • 【lucene】tip文件详解
  • 高并发网络编程实战:深入理解epoll客户端的事件驱动模型
  • HAProxy使用方法以及和LVS区别
  • 图形自动化:pynput实现Win11系统动作点击录制与回放
  • axure chrome 浏览器插件的使用