八股临时总结

文章目录

一、原子操作的内部屏障

1、原子操作的功能

(1)保证这个变量的读写不可被打断;

(2)保证操作前后的内存访问顺序不会被编译器或CPU重排序;

2、原子内部屏障

(1)CAS(无锁同步机制,通过比较内存中的值是否等于期望值,如果相等则更新为新值,否则失败并重试)

(2)memory-barrier(内存屏障 )防止CPU和编译器为了优化,把代码执行顺序乱掉

release/acquire通常通过memory barrier实现

acquire和release

Acquire Release
保证当前线程读到的数据是最新的 保证本线程对数据的修改是其他线程可见的
cpp 复制代码
#include <atomic>
#include <iostream>
#include <thread>

std::atomic<bool> ready{false};
int data = 0;

void producer() {
    data = 42;          // 步骤 1: 准备数据
    // Release: 保证 data = 42 绝对不会被重排到这句代码的【后面】
    ready.store(true, std::memory_order_release); 
}

void consumer() {
    // Acquire: 保证读到 true 之后,后续的代码绝对不会被重排到这句代码的【前面】
    while (!ready.load(std::memory_order_acquire)) {
        // 等待
    }
    
    // 步骤 3: 读取数据
    // 绝对安全!因为 Acquire 和 Release 配对,
    // producer 中在 release 之前的所有修改(data=42),
    // 在 consumer 中 acquire 之后必然可见!
    std::cout << data << std::endl; // 永远输出 42
}

int main() {
    std::thread t1(producer);
    std::thread t2(consumer);
    t1.join();
    t2.join();
    return 0;
}

二、虚函数表实现原理

2.1 为什么需要虚函数?

C++默认函数调用都是静态绑定:

cpp 复制代码
class Base {
public:
    void func(){
        cout<<"Base";
    }
};

class Derived: public Base {
public:
    void func(){
        cout<<"Derived";
    }
};


Base* ptr = new Derived();
ptr->func();

输出:Base

因为在编译阶段就已经确定调用了Base::func

如果希望:利用基类Base类型指针调用派生类func,则需要虚函数

cpp 复制代码
class Base{
public:
	virtual void func(){
		cout<<"Base";
	}
};

这就是多态!

2.2 虚函数表是什么?

当一个类包含虚函数时,编译器会给这个类增加一个隐藏成员:虚函数表;

调用过程:

cpp 复制代码
Base* p = new Derived();

p->func();
  1. 根据p找到对象
  2. 找到对象里的vptr
  3. 根据vptr找到vtable
  4. 找到对应函数地址
  5. 调用派生类Derived::func()

通过虚函数表记录,实现动态绑定;

2.3 虚函数表的开销?

2个:

(1)对象增加一个指针:vptr(8字节)

(2)多一次间接寻址:加载 vptr -> 加载 func address -> 调用

2.4 析构函数为什么经常写virtual?

普通的析构函数,在通过基类ptr执行析构函数时,不会将其派生类对象析构掉,会造成:内存泄露。

回答总结:

  • C++虚函数通过vptr和vtable实现运行时多态。包含虚函数的对象内部维护一个虚函数表指针,指向存储虚函数地址的表。
  • 当通过基类指针调用虚函数时,会根据vptr查找到其真实函数的地址,从而调用派生类实现;

三、智能指针使用场景和内存管理

普通指针会存在忘记delete的问题,所以利用智能指针方便管理(直接自动管理)

类型 特点 场景
unique_ptr 唯一所有权 资源管理 :谁创建谁释放
shared_ptr 共享所有权 多个模块共享,存在问题:多线程同步
weak_ptr 观察,不拥有 解决循环引用

四、多线程同步机制

多个线程同时访问共享资源导致数据竞争

重量级方式:

4.1 mutex互斥锁

cpp 复制代码
std::mutex m;


m.lock();

count++;

m.unlock();

4.2 atomic原子操作

针对简单变量:

cpp 复制代码
std::atomic<int> count;

count++;

内部支持CAS

读取旧值

比较是否改变

如果没有改变

更新

否则重试

4.3 生产者、消费者模式

消费者:没有数据就wait()

生产者:开始生产就notify()

4.4 semaphore信号量

控制资源数量

例如:GPU任务队列

acquire()获取

执行任务

release()释放

相关推荐
乐观勇敢坚强的老彭10 小时前
C++ 竞赛常用算法模板速查表
开发语言·c++·算法
我变成萤火虫11 小时前
河南萌新联赛2026第(三)场:郑州轻工业大学
数据结构·c++·算法·贪心算法·stl·深度优先·哈希算法
buhuizhiyuci11 小时前
【Linux 篇】数字世界的水流蓄水池 —— IO 缓冲区机制深度实战解析
linux·运维·服务器·c++
liulilittle11 小时前
LLM 推理引擎与内核系统工程原理
c++·ai·llm·内存·memory·core·kernel
啦啦啦啦啦zzzz12 小时前
moduo网络库 Acceptor TcpConnection
服务器·网络·c++·reactor·网络库
键盘会跳舞12 小时前
C++:右值引用与移动语义源码级深度拆解——现代C++性能优化的语言基石
c++·右值引用·移动语义
码匠许师傅12 小时前
【C++ 面试真题】聊聊 C++ 的虚函数和多态
java·c++·面试
lidtao13 小时前
青少年信息学奥赛C++四阶段学习路线(L1-L4完整体系)
c++·学习·软件工程·教培资源分享
djjjx.13 小时前
【 C++ 】多态
开发语言·c++·多态
鸿芯微控科技13 小时前
MFC关断后还有流量怎么办?零流量、阀门泄漏、压差与Python分析
c++·python·mfc·质量流量控制器·关断泄漏·零流量测试