C++11使用chrono获取当前时间戳

在 C++ 中,获取当前时间戳最推荐的方式是使用 C++11 引入的 <chrono> 库,它提供了高精度、类型安全的时间操作。根据需求,可以获取不同精度的时间戳(如秒、毫秒、微秒、纳秒)。

下面是几种常见场景的示例代码:

1. 获取秒级时间戳(自 1970-01-01 以来的秒数)

cpp

复制代码
#include <iostream>
#include <chrono>

int main() {
    // 获取当前时间点
    auto now = std::chrono::system_clock::now();
    // 转换为 time_t 类型(秒精度)
    std::time_t timestamp = std::chrono::system_clock::to_time_t(now);
    std::cout << "秒级时间戳: " << timestamp << std::endl;
    return 0;
}

2. 获取毫秒级时间戳

cpp

复制代码
#include <iostream>
#include <chrono>

int main() {
    auto now = std::chrono::system_clock::now();
    // 从纪元到现在的毫秒数
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
        now.time_since_epoch()
    );
    std::cout << "毫秒级时间戳: " << ms.count() << std::endl;
    return 0;
}

3. 获取微秒级时间戳

cpp

复制代码
#include <iostream>
#include <chrono>

int main() {
    auto now = std::chrono::system_clock::now();
    auto us = std::chrono::duration_cast<std::chrono::microseconds>(
        now.time_since_epoch()
    );
    std::cout << "微秒级时间戳: " << us.count() << std::endl;
    return 0;
}

4. 获取纳秒级时间戳(如果系统时钟支持)

cpp

复制代码
#include <iostream>
#include <chrono>

int main() {
    auto now = std::chrono::system_clock::now();
    auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
        now.time_since_epoch()
    );
    std::cout << "纳秒级时间戳: " << ns.count() << std::endl;
    return 0;
}

5. 使用 std::time 的简化方式(秒精度,C 风格)

cpp

复制代码
#include <iostream>
#include <ctime>

int main() {
    std::time_t timestamp = std::time(nullptr);
    std::cout << "秒级时间戳: " << timestamp << std::endl;
    return 0;
}

注意事项:

  • std::chrono::system_clock 的时间点通常表示 UTC 时间,其纪元(epoch)是 1970-01-01 00:00:00 UTC。

  • duration_cast 用于转换不同精度,如果需要浮点数秒(例如 1.234 秒),可以使用 duration<double>

  • C++20 引入了更便捷的 std::chrono::clock_cast 和日历扩展,但上述代码在 C++11 及以上均可编译。

如果想统计时间差(如某个函数执行时长),可用以下方法。

6. 基础用法:测量单次调用耗时(微秒/纳秒)

cpp

复制代码
#include <iostream>
#include <chrono>

// 示例函数:模拟耗时操作
void someFunction() {
    // 模拟工作负载
    for (volatile int i = 0; i < 1000000; ++i) {}
}

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

    someFunction();  // 要测量的函数

    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);

    std::cout << "函数耗时: " << duration.count() << " 微秒" << std::endl;
    return 0;
}

7. 使用宏或模板简化测量(自动打印耗时)

cpp

复制代码
#include <iostream>
#include <chrono>

#define MEASURE_TIME(func) do { \
    auto start = std::chrono::high_resolution_clock::now(); \
    func; \
    auto end = std::chrono::high_resolution_clock::now(); \
    auto dur = std::chrono::duration_cast<std::chrono::microseconds>(end - start); \
    std::cout << #func << " 耗时: " << dur.count() << " us" << std::endl; \
} while(0)

void myTask() {
    for (volatile int i = 0; i < 500000; ++i) {}
}

int main() {
    MEASURE_TIME(myTask());
    return 0;
}

8. 封装成通用计时器类(支持多次测量与平均值)

cpp

复制代码
#include <iostream>
#include <chrono>
#include <vector>

class Timer {
public:
    void start() {
        _start = std::chrono::high_resolution_clock::now();
    }

    void stop() {
        _end = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(_end - _start);
        _records.push_back(duration.count());
    }

    double getAverageMicroseconds() const {
        if (_records.empty()) return 0.0;
        double sum = 0.0;
        for (auto t : _records) sum += t;
        return sum / _records.size();
    }

    void clear() {
        _records.clear();
    }

private:
    std::chrono::time_point<std::chrono::high_resolution_clock> _start, _end;
    std::vector<long long> _records;
};

// 示例函数
int compute(int n) {
    int sum = 0;
    for (volatile int i = 0; i < n; ++i) sum += i;
    return sum;
}

int main() {
    Timer timer;
    const int iterations = 10;
    for (int i = 0; i < iterations; ++i) {
        timer.start();
        compute(1000000);
        timer.stop();
    }
    std::cout << "平均耗时: " << timer.getAverageMicroseconds() << " 微秒" << std::endl;
    return 0;
}

9. 注意编译器优化的影响

如果被测函数内部没有明显的副作用,编译器可能会将整个函数优化掉,导致测量结果接近 0。解决方法:

  • 使用 volatile 变量(如上例所示)。

  • 将计算结果输出或赋值给 volatile 变量。

  • 使用 #pragma optimize 关闭局部优化(不推荐)。

  • 使用基准测试框架(如 Google Benchmark)。

反例(可能被优化掉):

cpp

复制代码
void emptyLoop() {
    for (int i = 0; i < 1000000; ++i) {}  // 空循环可能被优化删除
}

修正:

cpp

复制代码
void notEmptyLoop() {
    volatile int sum = 0;
    for (int i = 0; i < 1000000; ++i) sum += i;
}

10. 高精度与不同精度的选择

  • std::chrono::high_resolution_clock:最高精度的时钟(通常是纳秒级)。

  • std::chrono::steady_clock:单调时钟,不受系统时间调整影响,适合测量间隔。

  • std::chrono::system_clock:系统实时时钟,可能被调整,不适合测量耗时。

推荐 :测量耗时优先使用 steady_clockhigh_resolution_clock(通常后者是前者的别名)。

cpp

复制代码
auto start = std::chrono::steady_clock::now();
// ... function ...
auto end = std::chrono::steady_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);

完整可运行示例(包含纳秒输出)

cpp

复制代码
#include <iostream>
#include <chrono>

void heavyWork() {
    volatile long long sum = 0;
    for (int i = 0; i < 1000000; ++i) {
        sum += i;
    }
}

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

    auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
    auto us = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

    std::cout << "耗时: " << ns.count() << " ns\n";
    std::cout << "耗时: " << us.count() << " us\n";
    std::cout << "耗时: " << ms.count() << " ms\n";
    return 0;
}

总结

  • 使用 <chrono>steady_clock + duration_cast

  • 注意防止编译器优化。

  • 多次测量取平均更可靠。

  • 对于复杂的性能分析,建议使用专门的 Profiler(如 perf, VTune)或 Google Benchmark 库。

如果需要测量一个函数在真实环境中的耗时(包含 I/O、锁竞争等),可以保持函数原样测量;如果只测量算法 CPU 时间,需排除其他干扰,可以多次调用取最小值或使用 std::chrono::steady_clock 配合高优先级线程。

相关推荐
为何创造硅基生物10 分钟前
C++ 类的 static 成员函数
c++
bubiyoushang88829 分钟前
基于 C/C++ 的 MQTT 物联网通信协议实现
c语言·c++·物联网
牛油果子哥q1 小时前
【C++ const 】全场景深度精讲:修饰规则、底层常量折叠、指针 / 引用 / 成员函数实战、易错坑点与工程代码实现
开发语言·c++
郝学胜_神的一滴1 小时前
Qt 高级开发 025:打造优雅界面的艺术与高效重构之道
c++·qt
牛油果子哥q1 小时前
【C++指针与引用】C++指针与引用底层彻底精讲:本质区别、易错深坑、底层内存模型、工程选型、笔试面试满分解析
c++·面试
十五年专注C++开发1 小时前
CMake实践:VS2019控制台程序隐藏控制台方法
c++·windows·cmake·控制台隐藏
小欣加油1 小时前
leetcode3635 最早完成陆地和水上游乐设施的时间II
数据结构·c++·算法·leetcode
QT-Neal2 小时前
链接和库整理
c++
剑锋所指,所向披靡!2 小时前
C++多线程实现
开发语言·c++·chrome
十五年专注C++开发2 小时前
Qt之QScopedPointer、QScopeGuard、QScopedValueRollback使用及源码解读
开发语言·c++·qt·qscopedpointer·qscopeguard