chrono库碰到的那些坑

本文探讨了C++中使用chrono库处理时间时遇到的异常情况,特别是当尝试输出不合理的时间值时出现的问题。通过实验对比,分析了chrono::system_clock::time_point::min()的特性,并给出了合理的解释。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看过c++标准程序库的同学都知道在介绍chrono库时有这段代码:

#include <iostream>
#include <chrono>
#include <string>
using namespace std;
string asString(const chrono::system_clock::time_point& tp)
{
    time_t t = chrono::system_clock::to_time_t(tp);
    string ts = _ctime64(&t);
    ts.resize(ts.size() - 1);
    return ts;
}
int main()
{
    auto tp = chrono::system_clock::now();
    cout << asString(tp) << endl;
    auto tp2 = chrono::system_clock::time_point::min();
    cout << asString(tp2);
    system("pause");
    return 0;
}

运行到asString(tp2)就会出现异常了,异常点如下:

static size_t __CLRCALL_OR_CDECL length(_In_z_ const _Elem * const _First) _NOEXCEPT // strengthened
        {   // find length of null-terminated string
        return (_CSTD strlen(_First));
        }

看这注释英文就知道我们试图输出一个空字符串(我用vs2017和qt creator调试都抛出异常)
由asString代码可知:
ts = ctime(&t);
ctime()函数返回的是char*,异常说我们抛出的异常是find length of null-terminated string,意思不就是这次返回的char*是个nullptr。
查了网络,问了人都无果,所以还是靠自己啊!!!
只能硬着头皮往后面翻了 c++ 标准程序库第三版是不是坑值得思考(毕竟我只是个小白)
此时出现第二段代码引起了我的思考:

#include <iostream>
#include <chrono>
#include <string>
using namespace std;

chrono::system_clock::time_point makeTimePoint(int year, int mon, int day, int hour, int min, int sec = 0)
{
    struct tm t;
    t.tm_year = year - 1900;
    t.tm_mon = mon - 1;
    t.tm_mday = day;
    t.tm_hour = hour;
    t.tm_min = min;
    t.tm_isdst = -1;
    t.tm_sec = sec;
    time_t tt = mktime(&t);
    /*if (tt == -1)
    throw "no valid system time";*/
    return chrono::system_clock::from_time_t(tt);
}

一开始我写错了,把1990写成了1990而且直接输出tt,最后得到tt为-1,这不正好不合理吗!!(用书上的数据)
后来我脑子聪明(知道反其道其行)

#include <iostream>
#include <chrono>
#include <string>
using namespace std;

chrono::system_clock::time_point makeTimePoint(int year, int mon, int day, int hour, int min, int sec = 0)
{
    struct tm t;
    t.tm_year = year - 1900;
    t.tm_mon = mon - 1;
    t.tm_mday = day;
    t.tm_hour = hour;
    t.tm_min = min;
    t.tm_isdst = -1;
    t.tm_sec = sec;
    time_t tt = mktime(&t);
    /*if (tt == -1)
    throw "no valid system time";*/
    return chrono::system_clock::from_time_t(tt);
}
string asString(const chrono::system_clock::time_point &tp)
{
    time_t t = chrono::system_clock::to_time_t(tp);
    string ts = ctime(&t);
    ts.resize(ts.size() - 1);
    return ts;
}
int main()
{

    auto tp = makeTimePoint(2010, 01, 01, 00, 00);
    cout << asString(tp);
    time_t t = chrono::system_clock::to_time_t(chrono::system_clock::time_point::min());
    /*tm *tt = localtime(&t);
    tp = makeTimePoint(tt->tm_year, tt->tm_mon, tt->tm_mday, tt->tm_hour, tt->tm_min);*/
    cout << asString(tp);
    system("pause");
    return 0;
}

注释的tt内容是运行不了的,因为得到是nullptr,这就说明chrono::system_clock::time_point::min()是得不到strcut tm也就更得不到ctime()返回的char*非nullptr了,而且查知chrono::system_clock::time_point::min()是负数,怎么可能用来表示时间
所以总结出:对于不合理的时间就别想着这样输出了,也没存在的意义
(也不知道写书的大佬是怎么搞出来的,望各位大佬赐教),不过我之前用__time32_t输出过min,max还是不行,,可能还有坑,我还是不深入了吧

<think>好的,我现在要帮用户了解C++chrono的详细用法和功能。首先,我需要回忆一下自己对chrono的了解,确保回答准确。chronoC++11引入的时间处理,主要用于处理时间点、时间段和时钟。用户可能想知道如何测量代码执行时间、处理定时任务或者进行时间转换等。 首先,我需要整理chrono的核心组件:时钟(Clocks)、时间点(Time Points)和持续时间(Durations)。这三个部分应该是回答的重点。用户提到的官方文档和使用方法,可能需要结合示例代码来说明,这样用户更容易理解。 接下来,我需要考虑用户可能的实际应用场景。比如,测量函数执行时间,这涉及到steady_clock和high_resolution_clock的区别,以及如何计算时间间隔。用户提供的引用中提到了使用std::chrono::steady_clock来记录时间点,并用duration计算持续时间,这部分应该详细说明。 另外,用户提供的引用里提到了同的时间单位,比如秒、毫秒、微秒,这些属于duration的模板参数。需要解释如何通过std::chrono::seconds、milliseconds等来指定时间单位,以及如何进行类型转换,比如duration_cast。 还有,用户可能对系统时钟和UTC时间转换感兴趣,比如获取当前时间并将其转换为可读的格式。这部分需要介绍system_clock和time_point的结合使用,以及如何通过std::chrono::system_clock::to_time_t转换成time_t,再使用std::ctime或者gmtime来格式化输出。 需要注意的是,用户可能对时间运算和比较太清楚,比如如何加减时间段,比较两个时间点的先后。这部分可以给出示例,比如时间点的加减操作和使用比较运算符。 另外,用户提到的引用3中提到了整数类型的精度,即duration<int, TimeUnit>,这可能涉及到duration模板的第一个参数表示存储的类型,可以是int、double等,需要解释同精度的选择对应用的影响。 还要考虑异常处理和同时钟的稳定性,比如steady_clock是单调递增的,适合测量时间间隔,而system_clock可能受系统时间调整的影响。这部分需要提醒用户在同场景下选择合适的时钟。 最后,根据用户提供的引用,可能需要指出如何结合线程休眠(sleep_for)和时间点来计算持续时间,如引用2中的示例代码所示。这可以展示chrono在实际编程中的应用,比如定时任务或性能测试。 总结下来,回答的结构应该分为几个部分:核心概念、时钟类型、时间段操作、时间点操作、时间转换与格式化、实际应用示例和相关问题。每个部分都需要用简洁的代码示例来说明,并确保符合用户提到的格式要求,比如行内公式用$...$,独立公式用$$...$$,过在这个问题中可能公式较少,但数学表达式需要注意格式。 另外,用户要求生成相关问题,我需要思考用户可能进一步询问的内容,比如chrono的线程安全、同精度时间单位的选择、处理时区转换的方法,或者与其他时间的对比等。这些问题可以作为相关问题的部分,帮助用户深入探索。 现在需要检查是否有遗漏的部分,比如duration的算术运算、时间点的差值计算,以及同时钟的epoch差异。确保覆盖用户可能需要的所有主要功能,并参考官方文档的结构来组织内容,使回答更具权威性。 最后,确保所有引用的内容正确标注,比如引用1、2、3在适当的位置加入引用标识,比如在测量执行时间时引用[^1][^2],在整数类型精度时引用[^3]。</think>以下是对C++ `std::chrono`时间的详细解析: --- ### 一、核心概念与功能 `std::chrono`提供**时间点**(`time_point`)、**持续时间**(`duration`)和**时钟**(`clock`)的抽象,支持高精度时间测量与计算。其核心功能包括: - **时间间隔计算**:如代码执行时间测量[^1] - **定时任务控制**:如线程休眠(`sleep_for`) - **时间转换与格式化**:如系统时间与UTC时间转换 --- ### 二、时钟(Clocks) 1. **`system_clock`** - 对应系统实时时钟,可转换为日历时间 - 示例:获取当前时间并格式化 ```cpp auto now = std::chrono::system_clock::now(); std::time_t t = std::chrono::system_clock::to_time_t(now); std::cout << "当前时间: " << std::ctime(&t); ``` 2. **`steady_clock`** - 单调递增时钟,适用于性能测量 - 示例:测量代码段耗时 ```cpp auto start = std::chrono::steady_clock::now(); // 执行代码 auto end = std::chrono::steady_clock::now(); auto duration = end - start; ``` 3. **`high_resolution_clock`** - 最高精度时钟(可能是`steady_clock`别名) --- ### 三、时间段(Duration) 表示时间间隔,模板参数为**数值类型**和**时间单位**: ```cpp using seconds = std::chrono::duration<int>; // 秒(默认单位) using milliseconds = std::chrono::duration<int, std::milli>; using microseconds = std::chrono::duration<double, std::micro>; ``` **操作示例**: ```cpp auto t1 = 2s; // C++14字面量语法 auto t2 = 500ms; auto sum = t1 + t2; // 自动转换为公共单位(2500ms) // 类型转换(需显式) auto sec = std::chrono::duration_cast<std::chrono::seconds>(sum); ``` --- ### 四、时间点(Time Point) 表示某一时刻,关联特定时钟: ```cpp using sys_time = std::chrono::time_point<std::chrono::system_clock>; auto epoch = sys_time{}; // 时钟的纪元起点(如1970-01-01) ``` **时间运算**: ```cpp auto tp = std::chrono::steady_clock::now(); auto later = tp + 10s; // 当前时间点+10秒 if (later > tp) { /* 比较时间点先后 */ } ``` --- ### 五、时间转换与格式化 1. **系统时间转字符串** ```cpp auto now = std::chrono::system_clock::now(); std::time_t t = std::chrono::system_clock::to_time_t(now); std::cout << "UTC时间: " << std::gmtime(&t)->tm_hour << "时"; ``` 2. **自定义时间单位转换** ```cpp auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(1s); std::cout << "1秒=" << ns.count() << "纳秒"; // 输出1秒=1000000000纳秒 ``` --- ### 六、实际应用示例 **性能测试代码段耗时**: ```cpp auto start = std::chrono::high_resolution_clock::now(); // 待测代码 auto end = std::chrono::high_resolution_clock::now(); std::chrono::duration<double> diff = end - start; std::cout << "耗时: " << diff.count() << "秒" << std::endl; ``` **定时任务控制**(引用自): ```cpp std::this_thread::sleep_for(std::chrono::duration<rl::math::Real>(2.6)); ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值