当前位置: 首页 > article >正文

C++常用的新特性-->day06

时间间隔duration

duration表示一段时间间隔,用来记录时间长度,可以表示几秒、几分钟、几个小时的时间间隔。duration的原型如下

// 定义于头文件 <chrono>
template<
    class Rep,
    class Period = std::ratio<1>
> class duration;

Rep:这是一个数值类型,表示时钟数(周期)的类型(默认为整形)。若 Rep 是浮点数,则 duration 能使用小数描述时钟周期的数目。
Period:表示时钟的周期,它的原型如下:

// 定义于头文件 <ratio>
template<
    std::intmax_t Num,
    std::intmax_t Denom = 1
> class ratio;

ratio类表示每个时钟周期的秒数,其中第一个模板参数Num代表分子,Denom代表分母,该分母值默认为1,因此,ratio代表的是一个分子除以分母的数值,比如:ratio<2>代表一个时钟周期是2秒,ratio<60>代表一分钟,ratio<6060>代表一个小时,ratio<6060*24>代表一天。而ratio<1,1000>代表的是1/1000秒,也就是1毫秒,ratio<1,1000000>代表一微秒,ratio<1,1000000000>代表一纳秒。

duration类的构造函数

// 1. 拷贝构造函数
duration( const duration& ) = default;
// 2. 通过指定时钟周期的类型来构造对象
template< class Rep2 >
constexpr explicit duration( const Rep2& r );
// 3. 通过指定时钟周期类型,和时钟周期长度来构造对象
template< class Rep2, class Period2 >
constexpr duration( const duration<Rep2,Period2>& d );

chrono库中根据duration类封装了不同长度的时钟周期(也可以自定义),基于这个时钟周期再进行周期次数的设置就可以得到总的时间间隔了(时钟周期 * 周期次数 = 总的时间间隔)。

综合案例

#include <chrono>
#include <iostream>
using namespace std;
int main()
{
    chrono::hours h(1);                          // 一小时
    chrono::milliseconds ms{ 3 };                // 3 毫秒
    chrono::duration<int, ratio<1000>> ks(3);    // 3000 秒

    // chrono::duration<int, ratio<1000>> d3(3.5);  // error
    chrono::duration<double> dd(6.6);               // 6.6 秒

    // 使用小数表示时钟周期的次数
    chrono::duration<double, ratio<1, 30>> hz(3.5);

    //count()统计的是时间周期
    cout << "count:" << h.count() << endl;
    cout << "count:" << ms.count() << endl;
    cout << "count:" << ks.count() << endl;
    cout << "count:" << dd.count() << endl;
    cout << "count:" << hz.count() << endl;

    cout << "************************************************************" << endl;

    chrono::milliseconds mss{ 3 };         // 3 毫秒
    chrono::microseconds uss = 2 * mss;     // 6000 微秒
    // 时间间隔周期为 1/30 秒 --> 一共有3.5个时间周期,每个周期为1/30秒
    chrono::duration<double, ratio<1, 30>> hzz(3.5);

    //count()统计的是时间周期
    cout << "3 ms duration has " << mss.count() << " ticks\n"
        << "6000 us duration has " << uss.count() << " ticks\n"
        << "3.5 hz duration has " << hzz.count() << " ticks\n";

    cout << "************************************************************" << endl;

    chrono::minutes t1(10);
    chrono::seconds t2(60);
    chrono::seconds t3 = t1 - t2;
    cout << t3.count() << " second" << endl;

    cout << "************************************************************" << endl;

 //统一时钟周期
    //分子的最大公约数是1 分母的最小公倍数是1 ---> 统一为ration<1,1>
    chrono::duration<int, ratio<60, 1>> jb(10);
    chrono::duration<int, ratio<1,1>> jk(60);
    auto jkb = jb - jk;
    cout << "count:" << jkb.count() << endl;

    cout << "************************************************************" << endl;
    
    //分子的最大公约数是3 分母的最小公倍数是35 ---> 统一为ration<3,35>
    chrono::duration<int, ratio<9, 7>> ak(3);
    chrono::duration<int, ratio<6, 5>> m4(1);
    auto hql = ak - m4;//auto --> chrono::duration<int,ration<3,35>>
    cout << "count:" << hql.count() << endl;
}

在这里插入图片描述

时间点和时钟

时间点结构体

hrono库中提供了一个表示时间点的类time_point,该类的定义如下:

// 定义于头文件 <chrono>
template<
    class Clock,
    class Duration = typename Clock::duration
> class time_point;

它被实现成如同存储一个 Duration 类型的自 Clock 的纪元起始开始的时间间隔的值,通过这个类最终可以得到时间中的某一个时间点。
Clock:此时间点在此时钟上计量
Duration:用于计量从纪元起时间的 std::chrono::duration 类型

时间点time_point构造函数

// 1. 构造一个以新纪元(epoch,即:1970.1.1)作为值的对象,需要和时钟类一起使用,不能单独使用该无参构造函数
time_point();
// 2. 构造一个对象,表示一个时间点,其中d的持续时间从epoch开始,需要和时钟类一起使用,不能单独使用该构造函数
explicit time_point( const duration& d );
// 3. 拷贝构造函数,构造与t相同时间点的对象,使用的时候需要指定模板参数
template< class Duration2 >
time_point( const time_point<Clock,Duration2>& t );

时钟clocks

system_clock:系统的时钟,系统的时钟可以修改,甚至可以网络对时,因此使用系统时间计算时间差可能不准。
steady_clock:是固定的时钟,相当于秒表。开始计时后,时间只会增长并且不能修改,适合用于记录程序耗时
high_resolution_clock:和时钟类 steady_clock 是等价的(是它的别名)。

在使用chrono提供的时钟类的时候,不需要创建类对象,直接调用类的静态方法就可以得到想要的时间了。

成员类型描述
rep表示时钟周期次数的有符号算术类型
period表示时钟计次周期的 std::ratio 类型
duration时间间隔,可以表示负时长
time_point表示在当前时钟里边记录的时间点

system_clock

时钟类system_clock是一个系统范围的实时时钟。system_clock提供了对当前时间点time_point的访问,将得到时间点转换为time_t类型的时间对象,就可以基于这个时间对象获取到当前的时间信息了。

system_clock底层源码

struct system_clock { // wraps GetSystemTimePreciseAsFileTime/GetSystemTimeAsFileTime
    using rep                       = long long;
    using period                    = ratio<1, 10'000'000>; // 100 nanoseconds
    using duration                  = chrono::duration<rep, period>;
    using time_point                = chrono::time_point<system_clock>;
    static constexpr bool is_steady = false;

    _NODISCARD static time_point now() noexcept 
    { // get current time
        return time_point(duration(_Xtime_get_ticks()));
    }

    _NODISCARD static __time64_t to_time_t(const time_point& _Time) noexcept 
    { // convert to __time64_t
        return duration_cast<seconds>(_Time.time_since_epoch()).count();
    }

    _NODISCARD static time_point from_time_t(__time64_t _Tm) noexcept 
    { // convert from __time64_t
        return time_point{seconds{_Tm}};
    }
};

静态方法

// 返回表示当前时间的时间点。
static std::chrono::time_point<std::chrono::system_clock> now() noexcept;
// 将 time_point 时间点类型转换为 std::time_t 类型
static std::time_t to_time_t( const time_point& t ) noexcept;
// 将 std::time_t 类型转换为 time_point 时间点类型
static std::chrono::system_clock::time_point from_time_t( std::time_t t ) noexcept;

system_clock案例

#define _CRT_SECURE_NO_WARNINGS

#include <chrono>
#include <iostream>
using namespace std;
using namespace std::chrono;
int main()
{
    // 新纪元1970.1.1时间
    system_clock::time_point epoch;
    
    chrono::hours h(10 * 24);
    system_clock::time_point epoch1 = epoch + h;
    system_clock::time_point epoch2(epoch + h);

    //当前的时间
    system_clock::time_point nowTime = system_clock::now();
    //时间点 -> 时间段(单位秒)
    time_t allSec = system_clock::to_time_t(nowTime);
    //时间格式化 -> 通过ctime转化为字符串
    cout << "当前的时间:" << ctime(&allSec) << endl;

    //时间段转化为时间点
    system_clock::time_point tp = system_clock::from_time_t(allSec);
}

steady_clock

在C++11中提供的时钟类steady_clock相当于秒表,只要启动就会进行时间的累加,并且不能被修改,非常适合于进行耗时的统计。

底层源码

struct steady_clock { // wraps QueryPerformanceCounter
    using rep                       = long long;
    using period                    = nano;
    using duration                  = nanoseconds;
    using time_point                = chrono::time_point<steady_clock>;
    static constexpr bool is_steady = true;

    // get current time
    _NODISCARD static time_point now() noexcept 
    { 
        // doesn't change after system boot
        const long long _Freq = _Query_perf_frequency(); 
        const long long _Ctr  = _Query_perf_counter();
        static_assert(period::num == 1, "This assumes period::num == 1.");
        const long long _Whole = (_Ctr / _Freq) * period::den;
        const long long _Part  = (_Ctr % _Freq) * period::den / _Freq;
        return time_point(duration(_Whole + _Part));
    }
};

静态方法

static std::chrono::time_point<std::chrono::steady_clock> now() noexcept;

案例

#define _CRT_SECURE_NO_WARNINGS

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

void steadyClockTest()
{
	auto p1 = steady_clock::now();
	for (int i = 0; i < 100; i++)
	{
		cout << "*";
	}
	cout << endl;
	auto p2 = steady_clock::now();
	auto d1 = p2 - p1;
	cout << "count:" << d1.count() << endl;
}

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

在这里插入图片描述
得到的值是纳秒,去掉9个0换算成秒

high_resolution_clock

同system_clock

转换函数

如果是对时钟周期进行转换:源时钟周期必须能够整除目的时钟周期(比如:小时到分钟)。
如果是对时钟周期次数的类型进行转换:低等类型默认可以向高等类型进行转换(比如:int 转 double)。
如果时钟周期和时钟周期次数类型都变了,根据第二点进行推导(也就是看时间周期次数类型)。
以上条件都不满足,那么就需要使用 duration_cast 进行显示转换。

duration_cast

通过这个函数可以对duration类对象内部的时钟周期Period,和周期次数的类型Rep进行修改

#define _CRT_SECURE_NO_WARNINGS

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

void durationCastTest()
{
	//分钟 -> 小时 
	hours h = duration_cast<hours>(minutes(60));
	cout << "60 minutes is " << h.count() << " hours\n";
	//小时 -> 分钟
	minutes m1 = hours(1);
	cout << "1 hour is " << m1.count() << " minutes\n";

	//浮点 -> 整形 --> 不建议会损失精度
	//seconds ss = duration<double> s(2.5);//err 
	seconds ss1 = duration_cast<seconds>(duration<double> (2.5));

	using mydouble = duration<double>;
	seconds ss2 = duration_cast<seconds>(mydouble(2.5));
	cout << "ss1.count():" << ss1.count() << endl;
	cout << "ss2.count():" << ss2.count() << endl;

	//整形 -> 浮点
	mydouble dd = seconds(9);
	cout << "dd.count():" << dd.count() << endl;

	//时钟周期数据类型和时钟周期都变了
	duration<int, ratio<1, 100>>t1(100);
	duration<double, ratio<1, 100>>t2(12.56);

	//duration<int, ratio<1, 100>>t3 = t2;//err double转int有问题
	duration<int, ratio<1, 100>>t3 = duration_cast<duration<int, ratio<1, 100>>>(t2);
	cout << "t3.count():" << t3.count() << endl;
	duration<double, ratio<1, 100>>t4 = t1;// >>>> 时钟周期和时钟周期的数据类型都不相同,看类型转化,由于是int转double是没问题的-->会进行隐式类型转化
	cout << "t4.count():" << t4.count() << endl;
}

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

在这里插入图片描述

time_point_cast

函数的作用是对时间点进行转换,因为不同的时间点对象内部的时钟周期Period,和周期次数的类型Rep可能也是不同的

#define _CRT_SECURE_NO_WARNINGS

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

void durationCastTest()
{
	//分钟 -> 小时 
	hours h = duration_cast<hours>(minutes(60));
	cout << "60 minutes is " << h.count() << " hours\n";
	//小时 -> 分钟
	minutes m1 = hours(1);
	cout << "1 hour is " << m1.count() << " minutes\n";

	//浮点 -> 整形 --> 不建议会损失精度
	//seconds ss = duration<double> (2.5);//err 
/*
	template< class Rep2 >
	constexpr explicit duration( const Rep2& r );
*/
	seconds ss1 = duration_cast<seconds>(duration<double> (2.5));

	using mydouble = duration<double>;
	seconds ss2 = duration_cast<seconds>(mydouble(2.5));

	duration<double>a(2.5);
	seconds ss3 = duration_cast<seconds>(a);

	cout << "ss1.count():" << ss1.count() << endl;
	cout << "ss2.count():" << ss2.count() << endl;
	cout << "ss3.count():" << ss3.count() << endl;

	//整形 -> 浮点
	mydouble dd = seconds(9);
	cout << "dd.count():" << dd.count() << endl;

	//时钟周期数据类型和时钟周期都变了
	duration<int, ratio<1, 100>>t1(100);
	duration<double, ratio<1, 100>>t2(12.56);

	//duration<int, ratio<1, 100>>t3 = t2;//err double转int有问题
	duration<int, ratio<1, 100>>t3 = duration_cast<duration<int, ratio<1, 100>>>(t2);
	cout << "t3.count():" << t3.count() << endl;
	duration<double, ratio<1, 100>>t4 = t1;// >>>> 时钟周期和时钟周期的数据类型都不相同,看类型转化,由于是int转double是没问题的-->会进行隐式类型转化
	cout << "t4.count():" << t4.count() << endl;
}

//时间段传入
template<typename Duration>
using MyTimePoint = time_point<system_clock, Duration>;

int main()
{
	durationCastTest();
	cout << "********************************" << endl;
	MyTimePoint<seconds> mPoint(seconds(100));
	MyTimePoint<milliseconds> millPoint(milliseconds(1000));

	//s->ms
	MyTimePoint<milliseconds> ms = mPoint;
	time_t tm1 = system_clock::to_time_t(ms);//时间点转化
	cout << "  " << ctime(&tm1);

	//ms->s
	//MyTimePoint<seconds> mss = millPoint;//err >>>>  
	MyTimePoint<seconds> mss = time_point_cast<seconds>(millPoint);
	time_t tm2 = system_clock::to_time_t(mss);
	cout << "  " << ctime(&tm2);

	return 0;
}

在这里插入图片描述

作者: 苏丙榅
链接: https://subingwen.cn/cpp/chrono/#1-2-%E7%B1%BB%E7%9A%84%E4%BD%BF%E7%94%A8


http://www.kler.cn/a/395374.html

相关文章:

  • 基于Spring Boot的在线性格测试系统设计与实现(源码+定制+开发)智能性格测试与用户个性分析平台、在线心理测评系统的开发、性格测试与个性数据管理系统
  • 38配置管理工具(如Ansible、Puppet、Chef)
  • 修改数据库和表的字符集
  • 如何向函数模块 FM 中传递 Range 参数
  • Tomcat 和 Netty 的区别及应用场景分析
  • 为什么hbase在大数据领域渐渐消失
  • 多窗口切换——selenium
  • 力扣 平衡二叉树-110
  • 【论文阅读】HITS: High-coverage LLM-based Unit Test Generation via Method Slicing
  • 【计算机视觉】FusionGAN
  • 【MySQL】数据库表连接简明解释
  • 【代码审计】常见漏洞专项审计-业务逻辑漏洞审计
  • TypeScript:现代 JavaScript 的超级集
  • rockylinux 8安装 gcc11.2
  • 用两行命令快速搭建深度学习环境(Docker/torch2.5.1+cu118/命令行美化+插件),包含完整的 Docker 安装步骤
  • 爬虫开发工具与环境搭建——环境配置
  • 火山引擎数据飞轮模式下的线上营销:内容产出更智能、人群触达更精准
  • Linux系统常用操作与命令指南
  • Apache服务安装
  • 单网页图库应用Single File PHP Gallery
  • 求知导刊期刊简介及投稿点评
  • 【go从零单排】URL Parsing(URL解析)
  • PyEcharts | 通过分析奥迪车购买数据来学习柱状折线复合图像的绘制方法
  • 风险数据集市整体架构及技术实现
  • 深度学习知识点1--编码器与解码器
  • 怎样在软件设计中选择使用GOF设计模式