<chrono> 是 C++ 标准库里专门处理时间、时长、计时器、时钟的库。它的设计目标是:

  • 类型安全
  • 精度清晰
  • 避免直接用裸整数表示时间导致单位混乱

可以把它理解成两大核心概念:

  1. duration(时长):表示“多长时间”,比如 3 秒、500 毫秒
  2. time_point(时间点):表示“某个时刻”,比如“从某个时钟起点开始经过了 10 秒的位置”

一、chrono 的核心组成

1. duration:时间间隔

std::chrono::duration 用来表示一段时间。

常见类型

1
2
3
4
5
6
std::chrono::seconds
std::chrono::milliseconds
std::chrono::microseconds
std::chrono::nanoseconds
std::chrono::minutes
std::chrono::hours

示例

1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <chrono>

int main() {
std::chrono::seconds s(5);
std::chrono::milliseconds ms(1500);

std::cout << s.count() << std::endl; // 5
std::cout << ms.count() << std::endl; // 1500
}

count() 方法

count() 用来取出 duration 内部存储的数值。

比如:

  • seconds(5).count()5
  • milliseconds(1500).count()1500

注意:count() 只返回数值,不带单位,单位由类型决定。


2. time_point:时间点

std::chrono::time_point 表示某个时钟上的一个时间点。

一般不直接手动构造,而是通过时钟获取:

1
auto now = std::chrono::system_clock::now();

这个 now 就是一个 time_point


3. clock:时钟

chrono 提供了几种常用时钟:

system_clock

系统时钟,对应当前真实世界时间,可以和日历时间转换。

1
auto now = std::chrono::system_clock::now();

适合:

  • 获取当前时间
  • 转换为年月日时分秒
  • 打印当前时间

steady_clock

单调时钟,不会倒退,适合测量时间间隔。

1
auto start = std::chrono::steady_clock::now();

适合:

  • 程序性能测试
  • 计算函数耗时
  • 超时控制

推荐测耗时优先用 steady_clock,因为系统时间可能被修改,而它不会受影响。


high_resolution_clock

高精度时钟,通常表示系统提供的最高精度时钟。

1
auto t = std::chrono::high_resolution_clock::now();

但它在不同实现里可能只是 system_clocksteady_clock 的别名,所以:

  • 如果你要稳定测耗时:优先 steady_clock
  • 如果你要当前现实时间:用 system_clock

二、chrono 常用操作


1. 获取当前时间:now()

1
auto now = std::chrono::system_clock::now();

或者:

1
auto now = std::chrono::steady_clock::now();

2. 计算时间差

两个 time_point 相减,得到一个 duration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <chrono>
#include <thread>

int main() {
auto start = std::chrono::steady_clock::now();

std::this_thread::sleep_for(std::chrono::seconds(2));

auto end = std::chrono::steady_clock::now();

auto diff = end - start;

std::cout << diff.count() << std::endl; // 默认单位取决于 diff 的类型
}

注意:这里 diff 的实际单位可能不是秒,而是时钟定义的周期。

通常我们会做类型转换。


3. duration_cast:时长转换

用于把一种时长单位转换成另一种。

示例

1
2
3
4
5
6
7
8
9
#include <iostream>
#include <chrono>

int main() {
auto ms = std::chrono::milliseconds(1500);
auto s = std::chrono::duration_cast<std::chrono::seconds>(ms);

std::cout << s.count() << std::endl; // 1
}

这里:

  • 1500 毫秒
  • 转成秒后得到 1 秒
  • 小数部分会被截断

再看一个耗时统计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <chrono>
#include <thread>

int main() {
auto start = std::chrono::steady_clock::now();

std::this_thread::sleep_for(std::chrono::milliseconds(1200));

auto end = std::chrono::steady_clock::now();

auto cost = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

std::cout << "耗时: " << cost.count() << " ms" << std::endl;
}

4. duration 的加减乘除

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <chrono>

int main() {
auto d1 = std::chrono::seconds(3);
auto d2 = std::chrono::milliseconds(500);

auto d3 = d1 + d2; // 自动推导公共单位
auto d4 = d1 - std::chrono::seconds(1);

std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(d3).count() << std::endl; // 3500
std::cout << d4.count() << std::endl; // 2
}

也支持比较:

1
2
3
if (std::chrono::seconds(1) < std::chrono::milliseconds(1500)) {
std::cout << "true" << std::endl;
}

5. time_point 的加减

时间点可以加减时长。

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <chrono>

int main() {
auto now = std::chrono::steady_clock::now();
auto later = now + std::chrono::seconds(5);
auto earlier = now - std::chrono::milliseconds(500);

auto diff = later - now;
std::cout << std::chrono::duration_cast<std::chrono::seconds>(diff).count() << std::endl; // 5
}

三、实际开发中最常用的场景


1. 测量代码执行时间

这是 chrono 最常见的用途。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <chrono>

void work() {
for (volatile int i = 0; i < 100000000; ++i);
}

int main() {
auto start = std::chrono::steady_clock::now();

work();

auto end = std::chrono::steady_clock::now();

auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

std::cout << "执行时间: " << elapsed.count() << " ms\n";
}

为什么用 steady_clock

因为它不会受系统时间调整影响,适合做性能计时。


2. 线程休眠

配合 <thread> 使用。

sleep_for

休眠一段时间

1
2
3
4
#include <thread>
#include <chrono>

std::this_thread::sleep_for(std::chrono::seconds(2));

sleep_until

休眠到某个时间点

1
2
auto wakeup = std::chrono::steady_clock::now() + std::chrono::seconds(3);
std::this_thread::sleep_until(wakeup);

3. 获取当前系统时间

1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <chrono>
#include <ctime>

int main() {
auto now = std::chrono::system_clock::now();
std::time_t t = std::chrono::system_clock::to_time_t(now);

std::cout << std::ctime(&t);
}

关键方法

  • system_clock::now():获取当前系统时间
  • system_clock::to_time_t():转为 time_t
  • system_clock::from_time_t():从 time_t 转回 chrono 时间点

4. 超时控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <chrono>

int main() {
auto start = std::chrono::steady_clock::now();
auto timeout = std::chrono::seconds(3);

while (true) {
auto now = std::chrono::steady_clock::now();
if (now - start > timeout) {
std::cout << "超时\n";
break;
}
}
}

四、C++14 / C++17 / C++20 中的便利写法

1. 字面量时间单位

std::chrono_literals 中定义。

1
using namespace std::chrono_literals;

这样你可以写:

1
2
3
auto t1 = 5s;
auto t2 = 100ms;
auto t3 = 10min;

示例

1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <chrono>
#include <thread>

using namespace std::chrono_literals;

int main() {
std::this_thread::sleep_for(2s);
std::cout << "2秒后执行\n";
}

这个写法非常常用,也更直观。


五、常见方法总结

下面是 chrono 里最常见的方法和操作:


1. clock::now()

获取当前时钟时间点

1
auto now = std::chrono::steady_clock::now();

2. duration::count()

获取时长的数值

1
2
auto s = std::chrono::seconds(10);
std::cout << s.count(); // 10

3. duration_cast<>()

时长类型转换

1
2
auto ms = std::chrono::milliseconds(1500);
auto s = std::chrono::duration_cast<std::chrono::seconds>(ms);

4. time_point 的加减

1
2
3
auto now = std::chrono::steady_clock::now();
auto future = now + std::chrono::seconds(1);
auto diff = future - now;

5. system_clock::to_time_t()

把 chrono 时间点转换成传统时间格式

1
2
auto now = std::chrono::system_clock::now();
std::time_t t = std::chrono::system_clock::to_time_t(now);

6. system_clock::from_time_t()

time_t 构造 chrono 时间点

1
2
std::time_t t = std::time(nullptr);
auto tp = std::chrono::system_clock::from_time_t(t);

7. sleep_for() / sleep_until()

线程等待

1
2
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::this_thread::sleep_until(std::chrono::steady_clock::now() + std::chrono::seconds(1));

六、一个完整例子

下面这个例子演示:

  • 获取开始时间
  • 模拟任务执行
  • 计算耗时
  • 输出当前系统时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <chrono>
#include <thread>
#include <ctime>

int main() {
// 1. 计时开始
auto start = std::chrono::steady_clock::now();

// 2. 模拟任务
std::this_thread::sleep_for(std::chrono::milliseconds(1500));

// 3. 计时结束
auto end = std::chrono::steady_clock::now();

// 4. 计算耗时
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::cout << "任务耗时: " << elapsed.count() << " ms\n";

// 5. 获取当前系统时间
auto now = std::chrono::system_clock::now();
std::time_t t = std::chrono::system_clock::to_time_t(now);

std::cout << "当前时间: " << std::ctime(&t);
}

七、容易混淆的点

1. durationtime_point 的区别

  • duration:时间长度
  • time_point:某个时刻

比如:

  • “5秒” 是 duration
  • “现在” 是 time_point

2. 为什么 end - start 不是秒?

因为不同 clock 的底层精度不同,减法结果是一个原始 duration,需要你显式转成秒、毫秒等。

1
2
auto diff = end - start;
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(diff);

3. system_clocksteady_clock 怎么选?

system_clock

  • 获取当前真实时间
  • 打印日志时间
  • 与日期时间转换

steady_clock

  • 测量耗时
  • 定时器
  • 超时判断

4. duration_cast 会截断

1
2
auto ms = std::chrono::milliseconds(1500);
auto s = std::chrono::duration_cast<std::chrono::seconds>(ms);

结果是 1 秒,不是 1.5 秒。

如果你想保留小数,可以用浮点 duration。

1
2
std::chrono::duration<double> sec = ms;
std::cout << sec.count() << std::endl; // 1.5

八、补充:浮点时长

如果你想得到小数秒:

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <chrono>
#include <thread>

int main() {
auto start = std::chrono::steady_clock::now();
std::this_thread::sleep_for(std::chrono::milliseconds(1500));
auto end = std::chrono::steady_clock::now();

std::chrono::duration<double> diff = end - start;
std::cout << "耗时: " << diff.count() << " 秒\n";
}

这里 diff.count() 可能输出 1.50012 这样的值。


九、总结

<chrono> 是 C++ 中用于表示时间长度、时间点、时钟和计时操作的标准库,最常用的内容是:

  • duration:表示时长
  • time_point:表示时刻
  • system_clock:真实系统时间
  • steady_clock:单调时钟,适合计时
  • now():获取当前时间点
  • count():取时长数值
  • duration_cast:转换时间单位
  • sleep_for() / sleep_until():线程等待