基础知识

一、C++ 基础语法

  1. C++ 和 C 的区别?

    • C++ 支持面向对象(封装、继承、多态)。
    • C++ 引入模板、STL、异常处理。
  2. 值传递、指针传递、引用传递的区别?

    • 值传递:拷贝一份副本。
    • 指针传递:传地址,可修改原数据。
    • 引用传递:别名,语法更简洁。
  3. const 的用法?

    • 修饰变量:常量。
    • 修饰指针:const int* p(指向常量),int* const p(常指针)。
    • 修饰成员函数:void f() const; 表示函数内不能修改成员变量。
  4. static 的作用?

    • 局部静态变量:函数调用间保持值。
    • 修饰全局变量/函数:只在文件内可见。
    • 修饰类成员:属于类而非对象。
  5. inline 内联函数的原理?

    • 编译器用函数体替换调用点,减少函数调用开销。
    • 适用于小函数,频繁调用。

二、面向对象

  1. C++ 四大特性?

    • 封装、继承、多态、抽象。
  2. 多态的实现方式?

    • 静态多态:函数重载、模板。
    • 动态多态:虚函数(虚函数表实现)。
  3. 虚函数、纯虚函数、抽象类区别?

    • 虚函数:子类可重写。
    • 纯虚函数:=0,子类必须实现。
    • 抽象类:含有纯虚函数,不能实例化。
  4. 虚函数表 (vtable) 的工作原理?

    • 类中有虚函数时,编译器生成 vtable,存储函数指针。
    • 对象包含 vptr,指向 vtable,实现动态绑定。
  5. 构造函数和析构函数的调用顺序?

    • 构造:先基类,再成员对象,最后派生类。
    • 析构:先派生类,再成员对象,最后基类。

三、内存管理

  1. C++ 内存分区?

    • 栈:局部变量、函数参数。
    • 堆:new/delete 分配的内存。
    • 全局/静态区:全局变量、静态变量。
    • 常量区:字符串常量。
    • 代码区:存放可执行代码。
  2. new/delete 与 malloc/free 的区别?

    • new 调用构造函数,返回指定类型指针。
    • malloc 只分配内存,不调用构造函数。
    • delete 调用析构函数,释放内存。
    • free 只释放内存。
  3. 内存泄漏如何检测?

    • 工具:Valgrind、ASan。
    • 手动:智能指针(shared_ptr, unique_ptr)。

四、C++11/14/17/20 新特性

  1. C++11 特性

    • auto 类型推导、nullptr、lambda、智能指针、右值引用、move 语义。
  2. 右值引用 & move 语义?

    • T&& 表示右值引用,用于接收临时对象。
    • std::move 转换为右值,避免拷贝,提高性能。
  3. 智能指针的区别?

    • unique_ptr:独占所有权。
    • shared_ptr:引用计数共享所有权。
    • weak_ptr:弱引用,不增加计数,解决循环引用。

五、STL

  1. vector 和 list 的区别?

    • vector:连续存储,随机访问快,插入删除慢。
    • list:链表存储,插入删除快,随机访问慢。
  2. map 和 unordered_map 的区别?

    • map:红黑树实现,元素有序,O(log n)。
    • unordered_map:哈希表实现,无序,O(1) 平均。
  3. 迭代器失效问题?

    • vector 插入/删除时可能导致迭代器失效。
    • list 插入/删除不会影响其他迭代器。

六、多线程与并发

  1. 线程创建方式?

    • std::thread
    • std::async
    • std::packaged_task
  2. 互斥锁和自旋锁区别?

    • 互斥锁:阻塞等待,适合长任务。
    • 自旋锁:忙等待,适合短任务。
  3. 条件变量 (condition_variable) 用法?

    • 结合 unique_lock,用于线程同步。

七、设计模式

  1. 单例模式实现?

    class Singleton {
    private:Singleton() {}
    public:static Singleton& getInstance() {static Singleton instance; // C++11 保证线程安全return instance;}
    };
    
  2. 工厂模式、观察者模式 —— 常考理论。


八、常见算法题型

  1. 二分查找模板

    int binarySearch(vector<int>& nums, int target) {int l = 0, r = nums.size() - 1;while (l <= r) {int mid = l + (r - l) / 2;if (nums[mid] == target) return mid;else if (nums[mid] < target) l = mid + 1;else r = mid - 1;}return -1;
    }
    
  2. 快速排序模板

    void quickSort(vector<int>& a, int l, int r) {if (l >= r) return;int i = l, j = r, pivot = a[l];while (i < j) {while (i < j && a[j] >= pivot) j--;while (i < j && a[i] <= pivot) i++;if (i < j) swap(a[i], a[j]);}swap(a[l], a[i]);quickSort(a, l, i-1);quickSort(a, i+1, r);
    }
    
  3. LRU 缓存(哈希表 + 双链表)

    • 高频考点,需熟练掌握。

九、综合类问题

  1. C++ 内存对齐规则?
  2. 深拷贝 vs 浅拷贝区别?
  3. 智能指针的循环引用问题怎么解决?
  4. 多态中析构函数为什么要设为虚函数?

高级知识点

一、 对象生存期与资源管理(RAII / Rule of Five)

  • RAII:资源由对象构造获取(constructor),析构释放(destructor)。推荐把资源封装在对象里,避免裸 new/delete。
  • Rule of Five:如果定义了自定义析构、拷贝/赋值/移动中的任意一个,通常要考虑五个函数:~T()T(const T&)T& operator=(const T&)T(T&&) noexceptT& operator=(T&&) noexcept
  • noexcept:移动构造/移动赋值应尽量标注 noexcept,因为很多 STL 容器在需要判断是否可用 noexcept move 时会选择拷贝或移动;若移动不是 noexcept,容器在扩容等操作时可能退回到拷贝(性能或语义影响)。

示例(拷贝-移动-释放的正确实现):

class Buffer {size_t n_;int* data_;
public:Buffer(size_t n=0): n_(n), data_(n ? new int[n]() : nullptr) {}~Buffer(){ delete[] data_; }// copyBuffer(const Buffer& o): n_(o.n_), data_(o.n_ ? new int[o.n_] : nullptr) {std::copy(o.data_, o.data_ + n_, data_);}Buffer& operator=(Buffer o){ // copy-and-swap 提供强异常安全swap(*this, o);return *this;}// moveBuffer(Buffer&& o) noexcept : n_(o.n_), data_(o.data_) {o.n_ = 0; o.data_ = nullptr;}Buffer& operator=(Buffer&& o) noexcept {if (this != &o) {delete[] data_;n_ = o.n_; data_ = o.data_;o.n_ = 0; o.data_ = nullptr;}return *this;}friend void swap(Buffer& a, Buffer& b) noexcept {using std::swap;swap(a.n_, b.n_);swap(a.data_, b.data_);}
};

面试点:为什么 operator=(Buffer o)(按值)提供强异常安全?因为拷贝发生在进入函数时,随后 swap 保证不会抛异常;若拷贝失败,原对象不受影响。


二、拷贝 vs 移动 vs 完美转发

  • std::move:将左值转换为右值(允许“移动”语义)。它只是类型转换,不做实际移动。
  • std::forward<T>:用于完美转发(保持值类别),常出现在模板转发场景(T&& 是 forwarding reference)。
  • 完美转发示例(容器 emplace 风格):
template<typename T>
void push_back_emplace(std::vector<T>& v, T&& val) {v.emplace_back(std::forward<T>(val)); // 保持传入值类别
}

面试点:区分 forwarding reference(模板 T&&)和纯右值引用。


三、 异常安全分级(面试必问)

  • 无保证(No guarantee):函数失败后程序状态不确定。
  • 基本保证(Basic):不泄露资源,对象处于有效但未定义的状态。
  • 强保证(Strong):要么成功,要么回滚到原状态(事务式)。
  • 不抛异常保证(No-throw):函数保证不抛异常(对析构函数很重要)。

实现强保证常用技术:copy-and-swap、先构造新对象再替换。


四、 Undefined Behavior(UB)——必须会举例并解释

常见 UB:

  • 访问释放后的内存(use-after-free)。
  • 双重释放(double free)。
  • 有符号整数溢出(int 溢出是 UB)。
  • 解引用空指针。
  • 同时无同步的并发读写(data race)。
    示例:
int a = INT_MAX;
int b = a + 1; // 有符号溢出 —— UB(不要假设会 wrap-around)

面试点:说明 UB 会让编译器基于假设做优化,从而产生难以预期的行为。


五、STL 深入(常被问到的细节)

  • push_back vs emplace_backemplace_back 直接在容器末构造对象(避免一次临时拷贝/移动)。

  • reserve:对 vector 预分配容量以避免多次 realloc(均摊复杂度)。

  • 容器复杂度与迭代器失效规则(面试常问)。举例:

    • vector:reallocation(如 push_back 导致容量增长)会使所有指针/引用/迭代器失效;在中间 insert/erase 会使其后的迭代器失效。
    • list / forward_list:插入/删除不影响除被删除元素外的迭代器(稳定迭代器)。
    • map(平衡树):插入/删除不会使其他元素的引用/迭代器失效(除了被删除的)。
    • unordered_maprehash 会使迭代器失效;插入可能导致 rehash。
  • allocator 基本概念:定制内存分配策略(进阶题)。

面试点:能解释为什么对 vector resize 可能触发移动还是拷贝(取决于元素是否可 noexcept move)。


六、 并发与内存模型(非常重要)

  • 数据竞争(Data race):两个或多个线程无同步地访问同一内存位置,且至少一个为写,程序行为未定义。
  • std::mutex / std::lock_guard / std::unique_lock:RAII 锁封装;std::scoped_lock 用于多锁防死锁。
  • std::atomic<T>:提供原子操作和内存序(memory_order_relaxed/acquire/release/seq_cst)。
  • compare_exchange_weak vs compare_exchange_strong:weak 可能虚假失败(适用于循环),strong 不会。
  • ABA 问题:CAS 仅比较值,若中间值先改为 B 再改回 A 会误判。常用解决:加版本号(tagged pointer)、使用 hazard pointers 或垃圾回收策略。
  • 线程同步经典题:std::condition_variable 的使用(生产者-消费者),std::call_oncestd::once_flag 做线程安全单例。

示例(线程安全单例,C++11 更简单):

MySingleton& instance() {static MySingleton inst; // C++11 保证线程安全的局部静态初始化return inst;
}

示例(简单生产者-消费者):

std::mutex mu;
std::condition_variable cv;
std::queue<int> q;void producer() {{std::lock_guard lk(mu);q.push(42);}cv.notify_one();
}void consumer() {std::unique_lock lk(mu);cv.wait(lk, []{ return !q.empty(); });int v = q.front(); q.pop();
}

七、 性能与优化实践(面试考点)

  • CPU 缓存友好(contiguous memory 优于链表),尽量让热点数据放在一起。
  • 减少内存分配(使用内存池 / reserve)。
  • 避免不必要的拷贝(move semantics、emplace)。
  • 关注分支预测、内联(inline)与编译器优化,先用 profiling(perf / gprof)确认热点,再优化。
  • 提前测量:microbenchmark(防止过早优化)。

八、 常见进阶题与样例实现(面试常问,附模板)

a) LRU Cache(O(1) get/put)

class LRUCache {int cap;list<int> keys;unordered_map<int, pair<int, list<int>::iterator>> mp;
public:LRUCache(int capacity): cap(capacity) {}int get(int k) {auto it = mp.find(k);if (it == mp.end()) return -1;keys.splice(keys.begin(), keys, it->second.second);return it->second.first;}void put(int k, int v) {auto it = mp.find(k);if (it != mp.end()) {it->second.first = v;keys.splice(keys.begin(), keys, it->second.second);return;}if ((int)mp.size() == cap) {int old = keys.back();keys.pop_back();mp.erase(old);}keys.push_front(k);mp[k] = {v, keys.begin()};}
};

面试点:解释 splice 的常数复杂度和为什么使用 list + unordered_map

b) 线程安全单例(call_once

class S {
public:static S& instance() {static std::once_flag f;static S* p = nullptr;std::call_once(f, []{ p = new S(); });return *p;}
private:S() = default;
};

c) Copy-swap 异常安全赋值

(见 Buffer 示例)


九、 调试与检测工具(面试可能问会用哪些)

  • AddressSanitizer (ASan):检测内存越界、use-after-free。
  • UndefinedBehaviorSanitizer (UBSan):检测 UB(如有符号溢出)。
  • ThreadSanitizer (TSan):检测 data race。
  • Valgrind:检测内存泄漏(Linux)。
  • gdb / lldb:调试断点、查看 backtrace。
  • perf / Flamegraphs:性能分析。

十、 高频面试问题(附要点回答)

  • 为什么要用 unique_ptr 而不是裸指针?
    → 表达所有权,自动释放,防止泄漏;shared_ptr 代价(引用计数)比 unique_ptr 高,且会引入循环引用风险。
  • std::move 之后对象状态如何?
    → 留在“可析构但未指定状态”,只能赋值或析构;使用前须重新赋值或立即处理。
  • volatile 在 C++ 中的作用?
    → 不用于线程同步;仅抑制某些编译器优化,真正并发应使用 std::atomic
  • 如何避免死锁?
    → 统一锁顺序、使用 std::scoped_lock、用 try_lock 超时退让、减少锁粒度。
  • 如何写高性能 IO / 内存敏感代码?
    → 减少 system call、使用缓冲、减少分配、考虑内存对齐/预取/向量化。

小建议

  • 练习方式:读题后写出 O(1)/O(n) 解法,然后讨论边界、异常安全、并发假设与性能瓶颈。
  • 面试时不要只写能过的代码,还要能解释时间/空间复杂度、是否有 UB、异常安全级别、并发安全假设与潜在改进。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/98344.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/98344.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/98344.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ES06-SpringData集成

ES06-SpringData集成 文章目录ES06-SpringData集成1-参考网址2-知识整理3-Spring Data Elasticsearch 9.0.0 完整示例4-知识补充1-Elasticsearch JAVA操作有三种客户端:1. TransportClient&#xff08;已废弃&#xff09;2. JestClient&#xff08;第三方 HTTP 客户端&#xff…

对于链表相关经典算法题:环形链表的约瑟夫问题的解析

开篇介绍&#xff1a; Hello 大家&#xff0c;在上一篇博客中&#xff0c;我们一同拆解了「206. 反转链表」和「876. 链表的中间结点」这两道单链表经典题目&#xff0c;通过对指针操作的细致打磨&#xff0c;相信大家对单链表的特性与算法设计思路有了更深入的理解。而在今天…

MySQL集群——主从复制

目录 一、环境搭建、部署 1. RHEL7.9、9.3的搭建 二、主从复制 1. 环境说明 2. 环境准备 1&#xff09;克隆RHEL79_mysql_master 2&#xff09;改名为 “RHEL79_mysql_slave” 并修改IP 3&#xff09;修改主机名 3. 部署MySQL主从同步 1&#xff09;主库(mysql-master) 2&…

《用 asyncio 构建异步任务队列:Python 并发编程的实战与思考》

《用 asyncio 构建异步任务队列:Python 并发编程的实战与思考》 一、引言:并发编程的新时代 在现代软件开发中,性能已不再是锦上添花,而是产品成功的基石。尤其在 I/O 密集型场景中,如网络爬虫、实时数据处理、微服务通信等,传统的同步编程模式往往力不从心。 Python …

【Linux】yum工具篇

目录一、软件包管理器1.1 什么是软件包1.2 Linux软件生态二、yum具体操作2.1 查找软件包2.2 安装软件包2.3 卸载软件配置文件所在路径个人主页<—请点击 Linux专栏<—请点击 一、软件包管理器 1.1 什么是软件包 在Linux下安装软件, 一个通常的办法是下载到程序的源代码…

撬动制造全场景增效,开利空调找到了怎样的“通关密码”?

由深圳软件协会指导、法大大和信息侠联合出品的《制造行业合同数智化升级白皮书》&#xff08;以下简称“白皮书”&#xff09;首次提出了 “电子签法律AI” 双轮驱动模型。在制造行业面临供应链协同、合规风控及全球化出海等多重挑战的当下&#xff0c;法大大依托丰富的制造企…

[Android]RecycleView的item用法

RecyclerView 是 Android 提供的一个强大的列表控件&#xff0c;用来显示大量数据。RecyclerView 的主要特点 1. 高性能的视图复用机制 Recycle就是循环的意思&#xff0c;那么recycleview的特点也很鲜明了&#xff0c;它只会创建出在屏幕内和一定缓存的itemview,当view滑出屏幕…

AI驱动的软件测试:革命性的自动化、缺陷检测与实验优化

引言在当今快节奏的软件开发生命周期&#xff08;SDLC&#xff09;中&#xff0c;传统测试方法已逐渐无法满足对速度、覆盖面和准确性的极高要求。人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;技术的融入&#xff0c;正在从根本上重塑软件测试的格…

继续优化基于树状数组的cuda前缀和

在之前的博客《借助树状数组的思想实现cuda版前缀和》中&#xff0c;我们用三个kernel实现了基于树状数组的cuda版前缀和&#xff0c;但是在数据量较大时速度不如传统的reduce-then-scan方法&#xff0c;主要原因在于跨block的reduce阶段没有充分利用所有的cuda核心。在本博客中…

Qt图片资源导入

右键项目&#xff0c;点击添加新文件 选择Qt -> Qt Resource File 资源文件起名 如&#xff1a;res 生成res.qrc文件 在项目的同级目录下创建文件夹res&#xff0c;并将准备好的资源粘贴进去 右键qrc文件&#xff0c;选中Open in Editor 添加前缀 前缀是各种类型图片的分类&…

嵌入式第四十六天(51单片机(中断,定时器))

一.独立按键设置1.#include "key.h"void init_key(void) {P1 | (0x0F << 4); }int key_pressed(void) {static int ret 0;if((P1 & (1 << 4)) 0){ret 1;}else if((P1 & (1 << 5)) 0){ret 2;}else if((P1 & (1 << 6)) 0){r…

Visual Studio Code2024安装包及安装教程

一、软件下载软件名称&#xff1a;Visual Studio Code 2024安装环境&#xff1a;window10及以上系统下载链接&#xff1a;https://pan.quark.cn/s/d9831b28c69a解压软件Bandizip下载链接&#xff1a;https://pan.quark.cn/s/a54e79b5d553二、软件安装1、下载后&#xff0c;先解…

fps:游戏玩法

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录游戏玩法倒计时僵尸潮游戏成功&失败计时玩法&#xff1a;玩家在计时内存活&#xff0c;成功&#xff1b;反之失败Game界面&#xff1a;由关卡调用计时系统计时完成&#xff1a;调用结果界面结果界面玩家死亡&…

如何建立针对 .NET Core web 程序的线程池的长期监控

如何建立针对 .NET Core web 程序的线程池的长期监控 建立针对 .NET Core Web 应用程序线程池的长期监控是一个系统性的工程&#xff0c;它涉及代码集成、指标收集、存储、可视化和告警。 核心思路 线程池监控不是孤立的&#xff0c;它必须与应用程序的整体性能指标&#xff08…

前端开发学习路径

前端开发学习路径前端开发基础技能HTML、CSS和JavaScript是前端开发的三大核心技术。HTML用于构建网页结构&#xff0c;CSS负责样式设计&#xff0c;JavaScript实现交互功能。掌握这三项技术是学习前端开发的基础。现代前端开发通常需要了解ES6语法&#xff0c;包括箭头函数、解…

一款没有任何限制的免费远程手机控制手机的软件简介

这是一款没有任何限制的免费远程手机控制手机的软件支持安卓和苹果1.安装1.1被控制端安装airdroid1.2控制端air mirror2.登录同一个账号3.控制使用打开控制端软件选择要控制的机器直接点“远程控制“连接上后就可以任意操作被控手机了

在word中使用lateX公式的方法

非常好的问题&#xff01;这是一个许多科研人员和学生都渴望实现的功能。但需要明确的是&#xff1a; **Microsoft Word 本身并不具备“自动”将 LaTeX 代码实时转换为渲染后公式的功能。** 它不像 Overleaf 或 VS Code 的 Markdown 插件那样&#xff0c;输入 $Emc^2$ 就立刻变…

23种设计模式——代理模式(Proxy Pattern)详解

✅作者简介&#xff1a;大家好&#xff0c;我是 Meteors., 向往着更加简洁高效的代码写法与编程方式&#xff0c;持续分享Java技术内容。 &#x1f34e;个人主页&#xff1a;Meteors.的博客 &#x1f49e;当前专栏&#xff1a;设计模式 ✨特色专栏&#xff1a;知识分享 &#x…

webpack scope hositing 和tree shaking

Scope Hoisting&#xff08;作用域提升&#xff09; 和 Tree Shaking&#xff08;摇树优化&#xff09; 是现代前端构建中至关重要的概念。它们是构建工具&#xff08;如 Webpack、Rollup、Vite&#xff09;用来优化最终打包产物的核心技术。 核心概念快速理解 Tree Shaking&am…

手写React状态hook

在日常开发中&#xff0c;我们经常用到 React 的状态管理 Hook&#xff1a;useState 和 useReducer。 但你有没有想过&#xff1a;这些 Hook 内部是怎么实现的&#xff1f;为什么调用 setState 之后组件会重新渲染&#xff1f; 今天我们就来从零手写 useState 和 useReducer&am…