RAII 计时器类
为了实现“自动统计终止时间”且不破坏业务逻辑的整洁性,我们可以封装一个计时器类。利用 C++ 对象的生命周期机制,将计时的开始点放在构造函数中,将计时的结束与统计点放在析构函数中。
原理:C++ 保证栈对象在离开其作用域(即遇到右大括号 })时,会自动调用析构函数。
利用匿名作用域:通过手动添加 { … } 代码块,我们可以精确控制计时器的生命周期,从而统计任意粒度(子过程 sub_stage)的耗时。
1 |
|
自动化与无侵入性:
不需要在每个 return 语句前都手动写一遍 end_time = now(); print();。
代码逻辑非常干净,计时逻辑与业务逻辑分离。
异常安全性(Exception Safety):
这是 RAII 最强大的地方。如果在子过程中抛出了异常(Exception),导致函数提前退出,栈展开(Stack Unwinding)机制依然会保证局部变量的析构函数被调用。
这意味着即使发生错误,我们依然能记录到该阶段截止目前的耗时,不会丢失监控数据。
灵活粒度控制:
正如题目中所述,利用 {} 可以随意圈定需要计时的范围,无需重构函数。
共享指针的共享计数常见实现方法有哪些?
主要有两种主流的实现策略:
外部控制块(Control Block / Auxiliary Block)—— 标准库 std::shared_ptr 的做法
原理:当智能指针初始化时,在堆上额外申请一块内存(控制块)。这个控制块内部包含:引用计数(ref_count)、弱引用计数(weak_count)、自定义删除器(deleter)等。
优点:非侵入式。任何类型的对象(包括基础类型 int)都可以被管理,不需要修改对象本身的定义。
侵入式计数(Intrusive Counting)—— 如 boost::intrusive_ptr
原理:将引用计数直接作为成员变量嵌入到被管理的对象内部。对象必须继承自特定的基类(包含计数器)。
优点:性能更高。少了一次堆内存分配(不需要控制块),且缓存局部性(Cache Locality)更好。这对高频交易(HFT)等高性能场景很有吸引力。