跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ 高精度时间库 chrono 详解

C++ 中的高精度时间库 chrono。首先对比了 C 语言 time.h 的不足,阐述了 chrono 的设计哲学,包括时间段、时间点和时钟三大核心概念。接着讲解了库中的各类单位,涵盖时长、时钟、日历基础及复合单位、时区和字面量。重点分析了 duration、time_point 等模板类及其接口,区分了 C++11 基础时钟与 C++20 新增专业时钟。此外,还介绍了日历类型的构建与运算、相关操作函数及 I/O 支持。最后通过日期计算类和内存池性能测试的代码示例,展示了 chrono 在实际开发中的应用。

战神发布于 2026/3/30更新于 2026/9/264 浏览
C++ 高精度时间库 chrono 详解

在 C 语言中,我们学习了时间库<time.h>。它操作简单、是全平台行为一致的时间库,但存在类型不安全、精度较低(通常为秒)、扩展依赖编译器宏等问题。

现代项目中如果要进行性能测试、时间间隔计算的话,C 语言的<time.h>显然不够。因此在 C++11 中,引入了这个时间库。

设计哲学

在 C++11 之前,处理时间基本靠 time_t、clock() 和 struct timespec。这种方式的问题在于:类型不安全。函数参数传递 time_t,你无法直观知道单位是秒还是毫秒;做时间运算时,极易因单位混淆导致 bug。

<chrono> 库最伟大的贡献,就是引入了 编译期类型安全 和 精度无关 的时间处理模型。它将时间抽象为三个核心概念:

  1. 时间段 (Duration):由 数值 和 单位 组成的强类型。例如 std::chrono::seconds(10) 就是 10 秒,std::chrono::milliseconds(1000) 是 1000 毫秒,它们在类型上就不同,不能直接隐式转换,避免了单位混淆。
  2. 时间点 (Time Point):某个特定时钟上的一个点,由 时钟 (Clock) 和 时间段 (Duration) 共同定义。它本质上是从某个固定的纪元 (Epoch) 开始到现在的时间段。例如 std::chrono::system_clock::now() 返回的就是一个时间点。
  3. 时钟 (Clock):提供了获取当前时间点的入口 (now()),并定义了时间点的精度和纪元。标准提供了三种时钟(如文档所列),这是新手最容易踩坑的地方。

库中的单位

时长单位(Duration Units)

这些是表示时间间隔的类型,基于 duration 模板定义。

单位名称引入标准说明
std::chrono::nanosecondsC++11纳秒,周期为 std::nano
std::chrono::microsecondsC++11微秒,周期为 std::micro
std::chrono::millisecondsC++11毫秒,周期为 std::milli
std::chrono::secondsC++11秒,周期为 std::ratio<1>
std::chrono::minutesC++11分钟,周期为 std::ratio<60>
std::chrono::hoursC++11小时,周期为 std::ratio<3600>
std::chrono::daysC++20天,周期为 std::ratio<86400>
std::chrono::weeksC++20周,周期为 std::ratio<604800>
std::chrono::monthsC++20月(平均格里高利月),周期为 std::ratio<2629746>
std::chrono::yearsC++20年(平均格里高利年),周期为 std::ratio<31556952>

时钟单位(Clock Types)

时钟定义了时间的原点(纪元)和刻度,用于产生时间点。

时钟名称引入标准说明
std::chrono::system_clockC++11系统范围实时时钟(挂钟时间),通常基于 Unix 时间戳
std::chrono::steady_clockC++11单调时钟,不受系统时间调整影响,适合测量间隔
std::chrono::high_resolution_clockC++11当前设置下最高精度的时钟,通常是上述之一的别名
std::chrono::utc_clockC++20协调世界时(UTC),处理跳秒
std::chrono::tai_clockC++20国际原子时(TAI),与 UTC 有固定偏移且无跳秒
std::chrono::gps_clockC++20全球定位系统时(GPS),始于 1980-01-06
std::chrono::file_clockC++20文件系统使用的时钟别名,用于获取文件时间戳
std::chrono::local_tC++20伪时钟,代表本地时间,不关联具体时区

日历基础单位(Calendar Fundamentals)

C++20 引入,表示格里高利历中的基本日期元素。

类型名称引入标准说明
std::chrono::dayC++20表示月份中的某一天(1-31)
std::chrono::monthC++20表示年份中的某个月(1-12)
std::chrono::yearC++20表示格里高利历中的年份(如 2024)
std::chrono::weekdayC++20表示星期几(0 代表周日,1 周一,...6 周六)
std::chrono::last_specC++20标签类,用于表示月份的最后一天或最后一个工作日

日历复合单位(Calendar Composites)

由基础类型组合而成,用于表示完整的日期或特定规则。

类型名称引入标准说明
std::chrono::year_monthC++20特定的年 + 月组合(如 2024y/May)
std::chrono::month_dayC++20特定的月 + 日组合(如 May/21d),忽略年份
std::chrono::year_month_dayC++20完整的日期(如 2024-05-21)
std::chrono::year_month_day_lastC++20某月的最后一天(如 2024 年 5 月的最后一天)
std::chrono::month_day_lastC++20某月的最后一天,忽略年份
std::chrono::year_month_weekdayC++20某年第 N 个月的星期 W(如 2024 年 5 月的第 3 个星期二)
std::chrono::year_month_weekday_lastC++20某个月的最后一个星期 W
std::chrono::month_weekdayC++20某个月的第 N 个星期 W,忽略年份
std::chrono::month_weekday_lastC++20某个月的最后一个星期 W,忽略年份
std::chrono::weekday_indexedC++20表示某个月的第几个星期几(如第 3 个星期二)
std::chrono::weekday_lastC++20表示某个月的最后一个星期几

时刻单位(Time of Day)

将时长拆分为时、分、秒等,用于表示一天内的时间。

类型名称引入标准说明
std::chrono::hh_mm_ssC++20将时长拆分为小时:分钟:秒及亚秒的模板类,支持 12 小时/24 小时格式

时区单位(Time Zone)

C++20 引入,用于处理时区、本地时间和转换。

类型名称引入标准说明
std::chrono::time_zoneC++20代表一个 IANA 时区(如"Asia/Shanghai")
std::chrono::zoned_timeC++20将时区与时间点关联的组合类型
std::chrono::tzdbC++20IANA 时区数据库的快照
std::chrono::sys_infoC++20特定时间点在某个时区的详细信息(偏移量、缩写、是否 DST)
std::chrono::local_infoC++20描述本地时间到系统时间转换的低级信息(用于处理歧义或不存在的时间)
std::chrono::chooseC++20枚举,用于指定在本地时间歧义时如何选择(earliest 或 latest)
std::chrono::time_zone_linkC++20时区的替代名称(链接)
std::chrono::nonexistent_local_timeC++20异常,表示本地时间不存在(如夏令时快进时段)
std::chrono::ambiguous_local_timeC++20异常,表示本地时间有歧义(如夏令时回拨时段)

字面量单位(Literals)

定义在 std::literals::chrono_literals 内联命名空间中,用于便捷书写。

字面量运算符引入标准返回类型/说明
operator""hC++14返回 std::chrono::duration,表示小时
operator""minC++14返回 std::chrono::duration,表示分钟
operator""sC++14返回 std::chrono::duration,表示秒
operator""msC++14返回 std::chrono::duration,表示毫秒
operator""usC++14返回 std::chrono::duration,表示微秒
operator""nsC++14返回 std::chrono::duration,表示纳秒
operator""yC++20返回 std::chrono::year,表示年份

模板类

std::chrono::duration

这是最核心的类模板,它将一个数值(tick 数)和一个时间单位(tick 周期)绑定在一起,实现了类型安全的时间长度表示。

template<class Rep,class Period = std::ratio<1>> class duration;
  • **Rep**:存储 tick 计数的算术类型,如 long long、int 或 double。
  • **Period**:一个 std::ratio 类型,编译期指定每个 tick 代表的秒数。例如,std::ratio<1> 为 1 秒,std::milli 为 1/1000 秒。

核心接口与表达式

接口类别表达式/代码示例作用与说明
构造函数duration<Rep, Period> d(5);用 tick 计数值构造时长。通常通过预定义类型或字面量创建,如 5s、100ms。
观察值d.count()返回底层的 tick 计数值(Rep 类型)。
算术运算d1 + d2, d1 - d2时长之间加减,返回相同单位的时长。
d * 3, d / 2时长乘以或除以一个标量(Rep 类型)。
比较运算d1 == d2, d1 < d2比较两个时长的长短(自动处理不同单位)。
单位转换duration_cast<seconds>(d)显式将时长转换为其他单位(可能截断)。
duration<double>(d)若目标 Rep 为浮点数,可隐式转换(无需 cast)。
特殊值duration::zero()返回零长度的时长。
duration::min()返回该时长类型能表示的最小值(最负值)。
duration::max()返回该时长类型能表示的最大值。

示例代码:

#include<iostream>
#include<chrono>
#include <ratio>
using namespace std::chrono;

void TestDuration() {
    // 1. 构造与观察
    milliseconds ms(1024);
    std::cout << ms.count() << " ms\n";
    
    // 2. 算术运算
    seconds s = duration_cast<seconds>(milliseconds(2500) + milliseconds(500));
    std::cout << s.count() << " s\n";
    
    // 3. 比较运算
    if (minutes(1) > seconds(30)) {
        std::cout << "1 分钟比 30 秒长\n";
    }
    
    // 4. 单位转换
    seconds s2 = duration_cast<seconds>(milliseconds(1500));
    std::cout << s2.count() << " s (截断后)\n";
    
    duration<double, std::ratio<60>> d_min = seconds(90);
    std::cout << d_min.count() << " 分钟\n";
}

std::chrono::treat_as_floating_point

这是一个类型特征(type trait),用于判断一个类型是否应被视为浮点数,从而决定是否允许从高精度到低精度的隐式转换。

template< class Rep > struct treat_as_floating_point : std::is_floating_point<Rep> {};
template< class Rep > constexpr bool treat_as_floating_point_v = treat_as_floating_point<Rep>::value;

它继承自 std::is_floating_point,因此默认情况下,只有当 Rep 是 float、double、long double 时,其值为 true。

核心规则与表达式

表达式值示例作用与说明
treat_as_floating_point_v<int>false指示 int 不被视为浮点数。
treat_as_floating_point_v<double>true指示 double 被视为浮点数。
编译期分支if constexpr (treat_as_floating_point_v<Rep>)在模板编程中,根据此特征选择不同的实现路径。
控制隐式转换duration<double, milli> d = seconds(1);允许:因为目标 Rep 为 double,treat_as_floating_point 为 true,1 秒 隐式转为 1000.0 毫秒。
duration<int, milli> d = seconds(1);禁止(编译错误):因为目标 Rep 为 int,treat_as_floating_point 为 false,隐式转换可能截断数据,必须用 duration_cast。

std::chrono::duration_values

这是一个工具类模板,它为给定的 Rep 类型提供了获取零值、最小值和最大值的统一静态接口。

template<class Rep> struct duration_values;

核心静态接口与表达式

静态函数表达式示例作用与说明
zero()duration_values<Rep>::zero()返回 Rep 类型的零值表示。通常为 Rep(0)。
min()duration_values<Rep>::min()返回 Rep 类型能表示的最小(最负)值。
max()duration_values<Rep>::max()返回 Rep 类型能表示的最大值。

主要用途:它主要被标准库内部用于实现 duration::zero()、duration::min() 和 duration::max() 成员函数。

时间点

time_point

这是最核心的类模板,它将一个时钟(Clock)和一个时长(Duration)结合起来,表示相对于该时钟纪元(epoch)的一个具体时间点。

template<class Clock, class Duration = typename Clock::duration> class time_point;
  • **Clock**:关联的时钟类型,如 system_clock、steady_clock。它定义了时间点的原点(纪元)。
  • **Duration**:用于度量从纪元到该时间点的时长的类型,默认为时钟的 duration 类型。

核心接口与表达式

接口类别表达式/代码示例作用与说明
构造函数time_point<Clock, Duration> tp;默认构造,创建一个值初始化的时间点。
time_point<Clock, Duration> tp(d);用 duration 构造一个时间点。
获取时长tp.time_since_epoch()核心观察函数。返回一个 Duration 类型的值,表示从时钟纪元到 tp 的时间长度。
算术运算tp + d, tp - d时间点 ± 时长 = 新的时间点。
tp1 - tp2两个时间点相减,得到一个 duration 对象,表示它们之间的时间间隔。
比较运算tp1 == tp2, tp1 < tp2比较两个时间点的先后顺序。
单位转换time_point_cast<duration>(tp)将时间点的内部时长单位显式转换为另一种 duration 类型。

clock_time_conversion

这是一个特性类(trait),它提供了在不同时钟的时间点之间进行转换的机制。在 C++20 中,随着新时钟(如 utc_clock)的引入,这个类变得尤为重要。

template<class Dest, class Source> struct clock_time_conversion;

核心接口与表达式

表达式作用与说明
通用形式clock_time_conversion<Dest, Source>{} 创建一个转换器对象。
converter(tp_source) 执行实际的转换。
C++20 常用转换示例clock_cast<Dest>(tp_source) (C++20):这是 clock_time_conversion 的简化包装。

时钟

在 <chrono 中,一个时钟类通常提供以下核心接口(以静态成员的形式):

接口表达式作用与说明
当前时间点clock::now()静态成员函数,返回当前时刻的 time_point。
时间点类型clock::time_point该时钟专属的时间点类型。
时长类型clock::duration该时钟的'原生'精度。
周期类型clock::period即 duration 的 Period 模板参数。
是否稳定clock::is_steady布尔值常量。true 表示该时钟是单调的。

C++11 的基础三时钟

这三个时钟从 C++11 起就存在,覆盖了绝大多数日常使用场景。

时钟名称核心特性典型用途是否稳定 (is_steady)
system_clock系统实时时钟(挂钟时间),通常基于 Unix 时间戳获取当前日期时间、与日历交互通常为 false
steady_clock单调时钟,只能向前移动,不受系统时间调整影响测量时间间隔、性能测试true
high_resolution_clock当前设置下具有最高精度的时钟需要最高精度计时的场景取决于底层别名

C++20 新增的专业时钟

C++20 极大地扩展了时钟家族,引入了处理不同时间标准的能力。

时钟名称核心特性与用途
utc_clock协调世界时(UTC)。处理跳秒。
tai_clock国际原子时(TAI)。连续的时间尺度,没有跳秒。
gps_clock全球定位系统时(GPS)。与 TAI 有固定偏移。
file_clock用于文件系统时间戳的时钟别名。
local_t伪时钟,标记与本地时间关联的时间点。

辅助模板:is_clock 与 is_clock_v

这是 C++20 引入的一个类型特征,用于在编译期判断一个类型是否符合时钟的要求。

表达式作用与说明
is_clock<T>::value如果类型 T 满足时钟的所有要求,则为 true。
is_clock_v<T>辅助变量模板,等同于 is_clock<T>::value。

日历

日历基础类型

这些是构成日期的基本原子类型,每个都封装了特定的日历字段。

类型名称引入标准核心接口与表达式作用与说明
dayC++20day d(21);构造一个表示某日的对象(1-31)。
monthC++20month m(5); 或 month m = May;构造一个表示某月的对象(1-12)。
yearC++20year y(2024); 或 2024y构造一个表示年份的对象。
weekdayC++20weekday wd(3); 或 wd = Wednesday;构造一个表示星期几的对象。
last_specC++20last(单例常量)标签类型,用于表示'月份的最后一天'。

日历复合类型

这些类型组合基础元素,表示更丰富的日期概念。

类型名称核心接口与表达式作用与说明
month_daymonth_day md = May/21d;表示'月/日'组合(无年份)。
year_monthyear_month ym = 2024y/May;表示'年/月'组合。
year_month_dayyear_month_day ymd = 2024y/May/21d;最常用的完整日期类型。
year_month_day_lastyear_month_day_last ymdl = 2024y/May/last;表示某年某月的最后一天。
year_month_weekdayyear_month_weekday ymwd = 2024y/May/Wednesday[3];表示'某年某月的第 N 个星期 W'。

关键运算符与函数

日历类型之所以强大,很大程度上归功于重载的运算符。

类别表达式作用与说明
创建运算符/最重要的创建语法。/ 被重载用于组合年、月、日。
算术运算+, -可以对 year_month 加减 months 或 years。
比较运算==, !=, <, <=, >, >=所有日历类型都支持全系列的比较运算符。
差值运算-两个 year_month_day 相减,返回 days 类型的时长。
流输出<<大多数日历类型都重载了 <<,可以直接 std::cout << ymd;。

代码示例

#include <iostream>
#include <chrono>
using namespace std::chrono;
using namespace std::literals;

int main() {
    // 1. 创建日期的多种方式
    auto ymd1 = 2024y / May / 21d;
    auto ymd2 = 21d / May / 2024;
    std::cout << "ymd1 = " << ymd1 << "\n";
    
    // 2. 访问日期字段
    std::cout << "年份:" << ymd1.year() << "\n";
    
    // 3. 日期算术
    auto ymd_next_month = ymd1 + months(1);
    std::cout << "下个月:" << ymd_next_month << "\n";
    
    // 4. 处理特殊日期:某月最后一天
    auto last_day_of_feb_2024 = 2024y / February / last;
    std::cout << "2024 年 2 月最后一天:" << last_day_of_feb_2024 << "\n";
    
    return 0;
}

函数

时长(Duration)操作函数

函数表达式引入标准简要说明
duration_cast<ToDuration>(d)C++11将时长 d 转换为其他单位,截断取整。
floor<ToDuration>(d)C++17将时长 d 向下取整。
ceil<ToDuration>(d)C++17将时长 d 向上取整。
round<ToDuration>(d)C++17将时长 d 四舍五入。
abs(d)C++17返回时长 d 的绝对值。

时间点(Time Point)操作函数

函数表达式引入标准简要说明
time_point_cast<ToDuration>(tp)C++11将时间点 tp 的内部时长单位转换为另一种 duration。
floor<ToDuration>(tp)C++17将时间点 tp 向下取整。
clock_cast<DestClock>(tp)C++20将时间点在不同时钟之间转换。

日历(Calendar)操作函数

C++20 引入,用于操作日期类型,提供算术和比较功能。

函数表达式类别涉及类型示例简要说明
算术运算day + days, month + months对日历类型进行加减运算,自动处理进位。
比较运算day == day, year < year所有日历类型都支持完整的比较运算符。
差值运算year_month_day - year_month_day返回 days 类型,表示两个日期的天数差。

输入/输出(I/O)函数

函数表达式引入标准简要说明
operator<<(os, duration)C++11输出时长(如 "5s")。
operator<<(os, sys_time)C++20输出各种时钟的时间点。
from_stream(is, fmt, day)C++20从输入流按照指定格式解析日历类型。

字面量(Literals)运算符

定义在内联命名空间 std::literals::chrono_literals 中,用于便捷书写时长和年份。

字面量运算符引入标准返回类型/说明
operator""hC++14返回 hours(小时时长)
operator""sC++14返回 seconds(秒时长)
operator""yC++20返回 year(年份)

测试

日期计算

以下代码需要 C++20 才能编译通过。

Date.h

#define _CRT_SECURE_NO_WARNINGS
#include <chrono>
#include <iostream>
#include <string>
#include< cassert >
class Date {
private:
    std::chrono::year_month_day ymd_;
public:
    // 1. 构造函数
    Date(const std::chrono::year_month_day& ymd) : ymd_(ymd) {
        if (!ymd_.ok()) {
            throw std::invalid_argument("Invalid date");
        }
    }
    Date(int year, int month, int day) : Date(std::chrono::year{ year } / month / day) { }

    // 2. 静态工厂:获取当前日期
    static Date today() {
        auto now = std::chrono::system_clock::now();
        auto today_days = std::chrono::floor<std::chrono::days>(now);
        return Date{ std::chrono::year_month_day{today_days} };
    }

    // 3. 访问器
    int year() const { return static_cast<int>(ymd_.year()); }
    unsigned month() const { return static_cast<unsigned>(ymd_.month()); }
    unsigned day() const { return static_cast<unsigned>(ymd_.day()); }
    unsigned weekday() const {
        std::chrono::weekday wd{ std::chrono::sys_days{ymd_} };
        return wd.c_encoding();
    }
    bool isLeapYear() const { return ymd_.year().is_leap(); }

    // 4. 日期算术运算符
    Date operator+(const std::chrono::days& d) const {
        auto sd = std::chrono::sys_days{ ymd_ } + d;
        return Date{ std::chrono::year_month_day{sd} };
    }
    Date operator-(const std::chrono::days& d) const { return *this + (-d); }
    Date operator+(const std::chrono::months& m) const {
        auto new_ymd = ymd_ + m;
        if (!new_ymd.ok()) {
            new_ymd = new_ymd.year() / new_ymd.month() / std::chrono::last;
        }
        return Date{ new_ymd };
    }
    Date operator-(const std::chrono::months& m) const { return *this + (-m); }
    Date operator+(const std::chrono::years& y) const {
        auto new_ymd = ymd_ + y;
        if (!new_ymd.ok()) {
            new_ymd = new_ymd.year() / new_ymd.month() / std::chrono::last;
        }
        return Date{ new_ymd };
    }
    Date operator-(const std::chrono::years& y) const { return *this + (-y); }

    // 5. 比较运算符
    auto operator<=>(const Date&) const = default;

    // 6. 差值计算
    std::chrono::days daysUntil(const Date& other) const {
        return std::chrono::sys_days{ other.ymd_ } - std::chrono::sys_days{ ymd_ };
    }
    int monthsUntil(const Date& other) const {
        int y1 = year(), m1 = month(), d1 = day();
        int y2 = other.year(), m2 = other.month(), d2 = other.day();
        int month_diff = (y2 - y1) * 12 + (m2 - m1);
        if (d2 < d1) { --month_diff; }
        return month_diff;
    }

    friend std::ostream& operator<<(std::ostream& os, const Date& date) {
        os << date.year() << '-' << (date.month() < 10 ? "0" : "") << date.month() << '-' << (date.day() < 10 ? "0" : "") << date.day();
        return os;
    }
};

DateTest.cpp

#define _CRT_SECURE_NO_WARNINGS
#include"Date.h"
using namespace std::chrono_literals;

void testDate() {
    std::cout << "=== 开始测试 Date 类 ===\n";
    
    // 1. 构造函数与 today()
    Date d1(2024, 5, 21);
    std::cout << " d1: " << d1 << "\n";
    assert(d1.year() == 2024 && d1.month() == 5 && d1.day() == 21);
    auto d_today = Date::today();
    std::cout << " Today: " << d_today << "\n";
    
    // 2. 无效日期抛出异常
    try {
        Date invalid(2024, 2, 30);
    } catch (const std::invalid_argument& e) {
        std::cout << "PASSED: 捕获异常 - " << e.what() << "\n";
    }
    
    // 3. 闰年判断
    assert(Date(2024, 1, 1).isLeapYear() == true);
    assert(Date(2023, 1, 1).isLeapYear() == false);
    
    // 4. 星期几
    assert(Date(2024, 5, 21).weekday() == 2); // 星期二
    
    // 5. 日期算术
    Date d2(2024, 5, 21);
    auto d_plus_7 = d2 + std::chrono::days(7);
    assert(d_plus_7 == Date(2024, 5, 28));
    
    auto d_plus_1m = d2 + std::chrono::months(1);
    assert(d_plus_1m == Date(2024, 6, 21));
    
    // 边界测试:月末
    Date d3(2024, 1, 31);
    auto d_plus_1m_jan = d3 + std::chrono::months(1);
    assert(d_plus_1m_jan == Date(2024, 2, 29)); // 2024 是闰年
    
    // 6. 比较运算符
    Date d6a(2024, 5, 21);
    Date d6b(2024, 5, 22);
    assert(d6a < d6b);
    
    // 7. 差值计算
    Date d7_start(2024, 5, 21);
    Date d7_end(2024, 12, 25);
    auto days_diff = d7_start.daysUntil(d7_end);
    assert(days_diff.count() == 218);
    
    std::cout << "=== 所有测试通过 ===\n";
}

int main() {
    testDate();
    return 0;
}

性能测试

本期我们以内存池为例,对比其与直接向系统 new/delete 的性能差距。

MemoryPool.h

#pragma once
#include <vector>
#include <cassert>
#include <iostream>
using std::vector;
using std::cout;
using std::endl;
namespace MyMemoryPool {
    constexpr inline size_t align_up(size_t n, size_t align) {
        return (n + (align - 1)) & ~(align - 1);
    }

    class FixedSizePool {
    public:
        explicit FixedSizePool(size_t blockSize, size_t blockPerPage = 1024)
            : block_Size(adjust_block_size(blockSize)),
              block_Per_Page(blockPerPage),
              free_list(nullptr),
              total_allocations(0),
              total_deallocations(0),
              page_count(0) {}

        ~FixedSizePool() {
            for (void* page : Pages) {
                ::operator delete[](page);
            }
        }

        void* allocate() {
            if (!free_list) expand();
            Node* head = free_list;
            free_list = head->next;
            ++total_allocations;
            return head;
        }

        void deallocate(void* p) {
            if (!p) return;
            Node* node = static_cast<Node*>(p);
            node->next = free_list;
            free_list = node;
            ++total_deallocations;
        }

        size_t Get_block_Size() const { return block_Size; }
        size_t Get_block_Per_Page() const { return block_Per_Page; }

        void print_stats() const {
            std::cout << "内存池统计:" << std::endl;
            std::cout << " 总分配次数:" << total_allocations << std::endl;
            std::cout << " 总释放次数:" << total_deallocations << std::endl;
            std::cout << " 当前使用中:" << (total_allocations - total_deallocations) << std::endl;
            std::cout << " 页数量:" << page_count << std::endl;
            std::cout << " 内存使用量:" << (page_count * block_Size * block_Per_Page) << " 字节" << std::endl;
        }

    private:
        struct Node {
            Node* next;
        };

        void expand() {
            size_t page_bytes = block_Size * block_Per_Page;
            char* page = static_cast<char*>(::operator new[](page_bytes));
            Pages.push_back(page);
            ++page_count;
            for (size_t i = 0; i < block_Per_Page; ++i) {
                char* block = page + i * block_Size;
                Node* n = reinterpret_cast<Node*>(block);
                n->next = free_list;
                free_list = n;
            }
        }

        size_t adjust_block_size(size_t s) const {
            size_t min_size = sizeof(void*);
            return align_up(s < min_size ? min_size : s, alignof(void*));
        }

        Node* free_list;
        size_t block_Size;
        size_t block_Per_Page;
        vector<void*> Pages;
        size_t total_allocations;
        size_t total_deallocations;
        size_t page_count;
    };
}

MPTest.cpp

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <chrono>
#include <vector>
#include "MemoryPool.h"
using namespace MyMemoryPool;
using namespace std::chrono;

template <typename AllocFunc, typename DeallocFunc>
double run_test(size_t iterations, AllocFunc alloc, DeallocFunc dealloc) {
    std::vector<void*> pointers;
    pointers.reserve(iterations);
    auto start = high_resolution_clock::now();
    for (size_t i = 0; i < iterations; ++i) {
        pointers.emplace_back(alloc());
    }
    for (void* p : pointers) {
        dealloc(p);
    }
    auto end = high_resolution_clock::now();
    duration<double> elapsed = end - start;
    return elapsed.count();
}

int main() {
    const size_t BLOCK_SIZE = 256;
    const size_t BLOCKS_PER_PAGE = 1024;
    const size_t ITERATIONS = 1000000;

    std::cout << "===== 性能对比测试 =====\n";
    std::cout << "块大小:" << BLOCK_SIZE << " 字节\n";
    std::cout << "每页块数:" << BLOCKS_PER_PAGE << "\n";
    std::cout << "分配/释放次数:" << ITERATIONS << "\n\n";

    // 1. 内存池测试
    {
        FixedSizePool pool(BLOCK_SIZE, BLOCKS_PER_PAGE);
        double pool_time = run_test(ITERATIONS, [&pool]() { return pool.allocate(); }, [&pool](void* p) { pool.deallocate(p); });
        std::cout << "内存池耗时:" << pool_time << " 秒\n";
        pool.print_stats();
    }
    std::cout << "\n";

    // 2. 直接 new/delete 测试
    {
        double new_time = run_test(ITERATIONS, []() { return ::operator new(BLOCK_SIZE); }, [](void* p) { ::operator delete(p); });
        std::cout << "new/delete 耗时:" << new_time << " 秒\n";
    }
    return 0;
}

熟练运用 <chrono> 可以在时间计算、性能测试等多方面领域大展身手!

目录

  1. <chrono>设计哲学
  2. 库中的单位
  3. 时长单位(Duration Units)
  4. 时钟单位(Clock Types)
  5. 日历基础单位(Calendar Fundamentals)
  6. 日历复合单位(Calendar Composites)
  7. 时刻单位(Time of Day)
  8. 时区单位(Time Zone)
  9. 字面量单位(Literals)
  10. 模板类
  11. std::chrono::duration
  12. std::chrono::treatasfloating_point
  13. std::chrono::duration_values
  14. 时间点
  15. time_point
  16. clocktimeconversion
  17. 时钟
  18. C++11 的基础三时钟
  19. C++20 新增的专业时钟
  20. 辅助模板:isclock 与 isclock_v
  21. 日历
  22. 日历基础类型
  23. 日历复合类型
  24. 关键运算符与函数
  25. 代码示例
  26. 函数
  27. 时长(Duration)操作函数
  28. 时间点(Time Point)操作函数
  29. 日历(Calendar)操作函数
  30. 输入/输出(I/O)函数
  31. 字面量(Literals)运算符
  32. 测试
  33. 日期计算
  34. 性能测试

更多推荐文章

查看全部
  • Python Selenium Web 自动化测试实战:博客系统全流程解析
  • 物联网固件 Web 管理接口漏洞挖掘与命令注入实战
  • DeepSeek 辅助降低论文 AIGC 检测率的指令与工具指南
  • BERT 模型详解:架构、原理与实战
  • Python 打包工具 auto-py-to-exe 使用指南
  • 基于 Python 与开源 AI 构建本地智能问答系统
  • C++ 多态详解:从概念到实现原理
  • 半小时基于 OpenClaw 搭建 AI 量化系统:开源三件套实测
  • Supabase 全栈开发实战:从云端服务到本地部署
  • 基于ESP32-C3的RISC-V智能家居中控实战
  • N8N 对接飞书多维表:数据增删改查实战指南
  • AI 语音合成新趋势:大模型驱动的自然韵律生成
  • Java 开发者转型 AI 大模型应用开发的学习路径与实战指南
  • C++ 哈希表封装与实现原理详解
  • C++ 性能优化实战:内存、CPU 与 I/O 效率提升指南
  • Midjourney 进阶:色调详解(上)
  • ClawdBot 快速上手:Web 控制台配置、设备授权与 Dashboard 访问
  • AI 绘画工具背后的视觉技术:Stable Diffusion 解析
  • AI 工具链实战:MLflow 实验跟踪
  • 生成式人工智能发展历程、现状与伦理挑战

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online