std::chrono
What problem does this section solve?
In C, handling time is done through functions like time(), clock(), sleep(), and gettimeofday(), which use different units and types (seconds, milliseconds, microseconds...). This can easily lead to confusion and lacks sufficient precision.
std::chrono is a type-safe time library introduced in C++11. It clearly separates the concepts of "time points", "durations", and "clocks", with units automatically managed within the type system, eliminating the need for manual conversion.
What is this feature?
std::chrono provides three core concepts:
- Duration
duration: A length of time, such as 5 seconds or 10 milliseconds. - Time Point
time_point: A specific moment, such as 2026-06-02 12:00:00. - Clock
clock: A tool for obtaining the current time, such assystem_clockandsteady_clock.
C++ standard version
C++11 (foundational), C++20 introduced calendar and timezone support, among other features.
Required header files
#include <chrono>
#include <thread> // for std::this_thread::sleep_for
Basic Syntax
using namespace std::chrono;
// 时长
auto t1 = 5s; // 5 秒
auto t2 = 100ms; // 100 毫秒
auto t3 = 50us; // 50 微秒
auto t4 = 10ns; // 10 纳秒
auto t5 = 1min; // 1 分钟(C++20)
auto t6 = 2h; // 2 小时(C++20)
// 时间点
auto now = std::chrono::system_clock::now(); // 当前时间(系统时钟)
auto now2 = std::chrono::steady_clock::now(); // 单调时钟(不会往回跳)
// 时长转换
auto sec = std::chrono::duration_cast<std::chrono::seconds>(100ms); // 0s(截断)
// 休眠
std::this_thread::sleep_for(500ms);
Common Clock Comparison
| clock | Features | Usage |
|---|---|---|
system_clock | System time, convertible to calendar time. | Display time, timestamp |
steady_clock | strictly increasing, never decreases | Time measurement (most commonly used) |
high_resolution_clock | Highest Precision Clock | Requires the highest precision timing |
Example code
Example 1: Measuring the execution time of a segment of code
#include <iostream>
#include <chrono>
#include <thread> // for sleep
int main()
{
using namespace std::chrono;
// 记录开始时间
auto start = steady_clock::now();
// 模拟耗时操作
std::this_thread::sleep_for(500ms);
// 记录结束时间
auto end = steady_clock::now();
// 计算耗时
auto elapsed = end - start;
auto elapsed_ms = duration_cast<milliseconds>(elapsed);
auto elapsed_us = duration_cast<microseconds>(elapsed);
std::cout << "Elapsed: " << elapsed_ms.count() << " ms\n";
std::cout << "Elapsed: " << elapsed_us.count() << " us\n";
return 0;
}
Running Result (approximately):
Elapsed: 500 ms
Elapsed: 500000 us
Example 2: Using and Converting Different Time Units Based on Example 1
#include <iostream>
#include <chrono>
int main()
{
using namespace std::chrono;
// 不同单位
auto s = 1s; // 1 秒
auto ms = 100ms; // 100 毫秒
auto us = 500us; // 500 微秒
// 时长可以相加
auto total = s + ms + us;
std::cout << "total in us: " << duration_cast<microseconds>(total).count() << " us\n";
// 秒到毫秒的转换
auto two_seconds = 2s;
auto as_ms = duration_cast<milliseconds>(two_seconds);
std::cout << "2s = " << as_ms.count() << " ms\n";
// 毫秒到秒的转换(会截断)
auto ms_to_sec = duration_cast<seconds>(1500ms);
std::cout << "1500ms = " << ms_to_sec.count() << " s\n"; // 1 秒
return 0;
}
Results:
total in us: 1100500 us
2s = 2000 ms
1500ms = 1 s
Example 3: Building on Example 2, implement a simple timer
#include <iostream>
#include <chrono>
#include <functional>
// 简单的计时器:测量函数运行时间
double measure(std::function<void()> func)
{
using namespace std::chrono;
auto start = steady_clock::now();
func();
auto end = steady_clock::now();
return duration_cast<microseconds>(end - start).count() / 1000.0; // 返回毫秒
}
void slow_operation()
{
int sum = 0;
for (int i = 0; i < 10000000; ++i)
{
sum += i;
}
std::cout << "sum = " << sum << "\n";
}
void quick_operation()
{
int sum = 0;
for (int i = 0; i < 1000; ++i)
{
sum += i;
}
std::cout << "sum = " << sum << "\n";
}
int main()
{
std::cout << "slow_op took " << measure(slow_operation) << " ms\n";
std::cout << "quick_op took " << measure(quick_operation) << " ms\n";
return 0;
}
Results may vary depending on the machine.
sum = 887459712
slow_op took 12.5 ms
sum = 499500
quick_op took 0.001 ms
Example 4: Get and format system time based on Example 3
#include <iostream>
#include <chrono>
#include <ctime>
#include <iomanip>
int main()
{
using namespace std::chrono;
// 获取当前系统时间
auto now = system_clock::now();
// 获取自 epoch(1970-01-01)以来的秒数
auto epoch_seconds = duration_cast<seconds>(now.time_since_epoch());
std::cout << "Seconds since epoch: " << epoch_seconds.count() << "\n";
// 转换为 C 风格的 time_t 打印
std::time_t now_c = system_clock::to_time_t(now);
std::cout << "Current time: " << std::ctime(&now_c);
// 计算未来时间点
auto future = now + 24h; // C++20 的 24h 字面量
// 如果没有 C++20,可以用: auto future = now + hours(24);
std::time_t future_c = system_clock::to_time_t(future);
std::cout << "24 hours later: " << std::ctime(&future_c);
return 0;
}
Running Results (date varies by run time):
Seconds since epoch: 1748870400
Current time: Mon Jun 2 12:00:00 2026
24 hours later: Tue Jun 3 12:00:00 2026
runtime results
See the "running results" for each example above.
Key syntax explanation in the example
|Here is the translation of the provided Simplified Chinese Markdown fragment into natural American English, following all specified rules.
| Example | Discusses what | Newly emerged syntax | Why write it this way | Precautions |
|---|---|---|---|---|
| Example 1 | Measuring code execution time | steady_clock::now(), duration_cast, literal 500ms | steady_clock monotonically increases, making it suitable for timing. | Literals require using namespace std::chrono |
| Example 2 | Time unit conversion | 1s、100ms、duration_cast | Types automatically manage units, requiring explicit casting during conversion. | duration_cast This is truncation, not rounding. |
| Example 3 | General-purpose timer | measure(function<void()>) | Package it into a reusable utility function. | steady_clock is the best choice |
| Example 4 | System time and formatting | system_clock::now()、to_time_t()、24h | system_clock can be converted to calendar time. | system_clock may be affected by system time adjustments and should not be used for timing purposes. |
Do not mix timing and display functions.
| Requirement | Recommended clock | Reason |
|---|---|---|
| Measure function execution time. | steady_clock | Monotonically increasing, unaffected by system time adjustments |
| Timeout check | steady_clock | Will not cause timeout errors due to system time jumps. |
| print the current date and time | system_clock | Can be converted to calendar time. |
| Generate log timestamp | system_clock | human-readable |
A common mistake is using system_clock for timeout checks. If the system time is adjusted backward by NTP or manually, the program might wait indefinitely without timing out. For measuring duration and handling timeouts, always prioritize using steady_clock.
Example 5: Using steady_clock for timeout judgment
#include <chrono>
#include <iostream>
#include <thread>
int main()
{
// 程序从 main 函数开始执行,下面的语句会按顺序运行。
using namespace std::chrono;
auto deadline = steady_clock::now() + 300ms;
while (steady_clock::now() < deadline)
{
std::cout << "waiting...\n";
std::this_thread::sleep_for(100ms);
}
std::cout << "timeout\n";
// 返回 0 表示程序正常结束。
return 0;
}
Possible results:
waiting...
waiting...
waiting...
timeout
The key here isn't the loop itself, but rather using steady_clock as the timeout benchmark. This pattern is very common in timers, serial read timeouts, and network wait timeouts.
Common Errors
Error 1: Forgetting using namespace std::chrono causes literals not recognized
auto t = 500ms; // ❌ 编译错误!
Correct approach: add using namespace std::chrono; or write std::chrono::milliseconds(500).
Error 2: Measuring elapsed time using system_clock
auto start = system_clock::now(); // ❌ 系统时间可能被人调回去了!
The correct approach: always use steady_clock for timing measurements.
Error 3: Forgot to use .count() and directly output duration
std::cout << duration_cast<milliseconds>(elapsed); // ❌ 不能直接输出
Correct approach: std::cout << elapsed_ms.count() << " ms\n";
Error 4: truncation issue of duration_cast
auto sec = duration_cast<seconds>(1500ms); // 1 秒!不是 1.5 秒
Correct approach: If decimals are needed, use duration<double> or duration_cast<milliseconds> to preserve precision.
使用建议
- 明确目标:在开始前确定您的具体需求,以便选择最合适的工具或教程。
- 充分利用资源:参考官方文档、教程和博客,这些资料能帮助您快速上手并解决问题。
- 实践应用:通过动手操作项目或编写代码来巩固学习成果,提升实际操作能力。
- 问题解决:遇到困难时,查阅参考资料或寻求社区支持,逐步培养独立解决问题的能力。
- 分享经验:完成项目后,可以撰写文章或博客分享心得,帮助其他学习者。
如果需要针对特定领域(如单片机、机器人或环境搭建)的进一步建议,请提供更多信息,我将为您细化内容。
- Measuring Time with
steady_clock:Monotonically increasing and unaffected by system time adjustments. - Displaying time using
system_clockcan be converted to calendar time. - Use literals like
1sand100msinstead of writing numbers directly: It's more readable. duration_castis truncation, not rounded off: precision will be lost—consider your usage scenarios.- C++20 adds calendar and timezone support:
std::chrono::year_month_day, and more, making it more powerful. - Timeout judgment also uses
steady_clock: Similar to measuring time consumption, it remains unaffected by system time adjustments.
Summary
std::chronoprovides type-safe time handling: duration, time_point, and clock.- Use
steady_clock::now()to measure elapsed time andsystem_clock::now()to obtain system time. - The literals
1s,100ms,50usmake the time code intuitive and readable. duration_castperforms unit conversion, and.count()gets the value.std::this_thread::sleep_for(500ms)makes a thread sleep.
Engineering expansion
In ROS2, the usage of rclcpp::Duration and rclcpp::Time is very similar to that of std::chrono. Once you have learned std::chrono, understanding ROS2's time handling becomes quite easy. In Boost.Asio, timers also make extensive use of std::chrono::duration.