首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C++大厂面试真题宝典 精选100道

C++大厂面试真题宝典 精选100道

原创
作者头像
用户11659095
发布2025-05-30 15:59:15
发布2025-05-30 15:59:15
2020
举报

从实战角度总结的C++性能优化案例,结合汇编视角分析底层原理,帮助理解优化本质:

案例1:循环展开(Loop Unrolling)

问题:循环控制开销占比高

代码语言:javascript
复制
cpp// 原始代码for(int i=0; i<1024; i++) {    sum += arr[i];} // 优化后(展开4次)for(int i=0; i<1024; i+=4) {    sum += arr[i] + arr[i+1] + arr[i+2] + arr[i+3];}

汇编视角

  • 原始代码:cmp, jl 指令反复执行1024次
  • 优化后:循环次数减少为256次,减少分支预测失败概率

案例2:分支预测优化

问题:条件分支导致流水线停滞

代码语言:javascript
复制
cpp// 原始代码(分支密集)if (x < 0) {    x = -x;} // 优化后(无分支版本)x = x < 0 ? -x : x;

汇编视角

  • 原始代码:test, jge 指令可能导致预测错误
  • 优化后:使用CMOV指令(条件移动)消除分支

案例3:内存访问对齐

问题:非对齐内存访问导致性能下降

代码语言:javascript
复制
cpp// 原始代码(未对齐)float* arr = (float*)malloc(N*sizeof(float)+1); // 故意不对齐 // 优化后alignas(64) float arr[N]; // 使用C++11对齐属性

汇编视角

  • 原始代码:movups(非对齐加载)
  • 优化后:movaps(对齐加载,吞吐量翻倍)

案例4:SIMD指令优化

问题:标量运算未利用向量单元

代码语言:javascript
复制
cpp// 原始代码(标量计算)for(int i=0; i<N; i++) {    a[i] = b[i] * c[i];} // 优化后(AVX2向量化)#include <immintrin.h>__m256 *a_vec = (__m256*)a;__m256 *b_vec = (__m256*)b;__m256 *c_vec = (__m256*)c;for(int i=0; i<N/8; i++) {    a_vec[i] = _mm256_mul_ps(b_vec[i], c_vec[i]);}

汇编视角

  • 原始代码:vmulss(单精度标量乘)
  • 优化后:vmulps(单指令8路并行乘)

案例5:消除假共享(False Sharing)

问题:多线程竞争同一缓存行

代码语言:javascript
复制
cpp// 原始代码(结构体紧凑布局)struct Data {    int a;    int b;} data[8]; // 优化后(添加填充)struct alignas(64) PaddedData {    int a;    char padding[60]; // 填充至64字节    int b;};PaddedData data[8];

汇编视角

  • 原始代码:多个线程频繁触发MOVNTDQA(非临时读取)
  • 优化后:每个线程操作独立缓存行,减少MESI协议开销

案例6:内联函数优化

问题:函数调用开销显著

代码语言:javascript
复制
cpp// 原始代码inline int add(int a, int b) { return a+b; } // 优化后(强制内联)__attribute__((always_inline)) inline int add(int a, int b) {    return a+b;}

汇编视角

  • 原始代码:call add 指令
  • 优化后:直接内联为add指令,消除调用栈开销

案例7:移动语义优化

问题:临时对象拷贝开销

代码语言:javascript
复制
cpp// 原始代码std::vector<std::string> v;v.push_back(std::string("hello")); // 触发拷贝 // 优化后v.emplace_back("hello"); // 直接构造

汇编视角

  • 原始代码:movaps 拷贝内存
  • 优化后:lea 直接计算地址,无拷贝操作

案例8:避免动态分配

问题:频繁new/delete导致内存碎片

代码语言:javascript
复制
cpp// 原始代码for(auto& obj : objects) {    obj = std::make_unique<Data>();} // 优化后(对象池)std::vector<Data> pool(1024);auto& obj = pool[idx++];

汇编视角

  • 原始代码:call operator new 频繁系统调用
  • 优化后:栈分配或预分配内存,无malloc指令

案例9:消除虚函数调用

问题:虚函数表查找开销

代码语言:javascript
复制
cpp// 原始代码class Shape { virtual void draw()=0; }; // 优化后(CRTP模式)template<typename Derived>class Shape {public:    void draw() { static_cast<Derived*>(this)->draw_impl(); }};

汇编视角

  • 原始代码:通过虚表指针mov rax, [rdi]查找函数地址
  • 优化后:直接调用call 目标函数,无间接跳转

案例10:循环交换(Loop Interchange)

问题:内存访问不连续

代码语言:javascript
复制
cpp// 原始代码(行优先访问)for(int i=0; i<N; i++) {    for(int j=0; j<M; j++) {        arr[i][j] = ...; // 列访问不连续    }} // 优化后(列优先访问)for(int j=0; j<M; j++) {    for(int i=0; i<N; i++) {        arr[i][j] = ...; // 行访问连续    }}

汇编视角

  • 原始代码:mov eax, [rsi+rdx*4] 步长不固定
  • 优化后:连续内存访问,利用prefetcht0预取

案例11:避免类型转换

问题:隐式类型转换开销

代码语言:javascript
复制
cpp// 原始代码double sum = 0.0;for(int i=0; i<N; i++) {    sum += arr[i]; // int到double隐式转换} // 优化后double sum = 0.0;for(int i=0; i<N; i++) {    sum += static_cast<double>(arr[i]); // 显式转换}

汇编视角

  • 原始代码:cvtsi2sd 隐式转换指令
  • 优化后:编译器可能优化为vmovsd 直接加载

案例12:编译器优化选项

问题:未充分利用编译器优化

代码语言:javascript
复制
bash# 原始编译g++ -O0 code.cpp # 优化后g++ -O3 -march=native code.cpp

汇编视角

  • -O0:包含调试信息,无优化
  • -O3:启用循环展开、内联、向量化等高级优化
  • -march=native:生成针对当前CPU的SIMD指令(如AVX-512)

核心优化原则

  1. 减少分支:降低分支预测失败率
  2. 提升局部性:利用CPU缓存(时间/空间局部性)
  3. 向量化:充分利用SIMD指令集
  4. 减少内存操作:避免缓存失效和页面错误
  5. 消除冗余:减少重复计算和临时对象

通过汇编视角分析,可以直观看到优化如何影响指令流水线、内存访问模式和CPU资源利用率,这是理解性能瓶颈的关键。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 案例1:循环展开(Loop Unrolling)
  • 案例2:分支预测优化
  • 案例3:内存访问对齐
  • 案例4:SIMD指令优化
  • 案例5:消除假共享(False Sharing)
  • 案例6:内联函数优化
  • 案例7:移动语义优化
  • 案例8:避免动态分配
  • 案例9:消除虚函数调用
  • 案例10:循环交换(Loop Interchange)
  • 案例11:避免类型转换
  • 案例12:编译器优化选项
  • 核心优化原则
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档