std::chrono类的简单使用实例及分析


author: hjjdebug

date: 2025年 05月 20日 星期二 14:36:17 CST

descrip: std::chrono类的简单使用实例及分析


文章目录

  • 1.实例代码:
  • [2. 代码分析:](#2. 代码分析:)
    • [2.1 auto t1 = std::chrono::high_resolution_clock::now();](#2.1 auto t1 = std::chrono::high_resolution_clock::now();)
      • [2.1.1 什么是 system_clock](#2.1.1 什么是 system_clock)
      • [2.1.2 什么是 chrono::time_point?](#2.1.2 什么是 chrono::time_point?)
      • [2.1.3 什么是duration?](#2.1.3 什么是duration?)
        • [2.1.3.1 duration 的一个实例](#2.1.3.1 duration 的一个实例)
      • [2.1.4 这么多的内涵,到底怎样理解time_point呢?](#2.1.4 这么多的内涵,到底怎样理解time_point呢?)
      • [2.1.5 time_point t1 在gdb中的表示](#2.1.5 time_point t1 在gdb中的表示)
    • [2.2 auto delta_t = t2 - t1;](#2.2 auto delta_t = t2 - t1;)
    • [2.3 auto dur_obj = std::chrono::duration<double, std::milli>(delta_t);](#2.3 auto dur_obj = std::chrono::duration<double, std::milli>(delta_t);)
      • [2.3.1 duration 对象能够知道数值代表的是毫秒,纳秒或者其它单位吗?](#2.3.1 duration 对象能够知道数值代表的是毫秒,纳秒或者其它单位吗?)

1.实例代码:

cpp 复制代码
$ cat main.cpp
#include <iostream>
#include <unistd.h> //for sleep
#include <chrono>
using namespace std;

int main() {
	//now()是类的静态函数, 
	auto t1 = std::chrono::high_resolution_clock::now(); //t1 是time_point 对象, time_point 对象是什么?
	// 被测代码
	sleep(1);
	auto t2 = std::chrono::high_resolution_clock::now();  // 返回的是时间点对象
	auto delta_t = t2 - t1; //2个time_point 对象相减,肯定被重构了. 返回的是 duration 对象, duration 对象是什么?
	
	auto dur_obj = std::chrono::duration<double, std::milli>(delta_t); //构造函数,参数是duration对象,返回ms为单位的duration对象
	std::cout << "耗时:" << dur_obj.count() << "ms" <<endl; //访问其数值,通过count(), 我们构建的是ms为单位的对象,所以单位就是ms
	dur_obj = std::chrono::duration<double, std::milli>(500); //另一个构造函数,给500就打印500,单位还是ms,由std::milli类型决定的.
	std::cout << "测试打印:" << dur_obj.count() << "ms" <<endl;
	return 0;
}

执行结果

$ ./temp

耗时:1000.14ms

测试打印:500ms

代码很短,可是内涵很丰富. 是c++模板类的入门之路.

下面几乎是逐句分析了.

2. 代码分析:

2.1 auto t1 = std::chrono::high_resolution_clock::now();

std: namespace

chrono: namespace

大命名空间下的小命名空间,此时的命名空间为std::chrono

using high_resolution_clock = system_clock;

using 与typedef 类似, 也与#define 有可比性. 就是说high_resolution_clock 这个类型

是 system_clock 类型的小名, 它们是一个类型. 由此引出 system_clock 类型

2.1.1 什么是 system_clock

cpp 复制代码
    struct system_clock
    { //定义了一堆类型别名, 告诉编译器说, 别慌, 有一堆类型记住它们的小名.
      typedef chrono::nanoseconds duration; //使用ns做duration
      typedef duration::rep rep;
      typedef duration::period period;
      typedef chrono::time_point<system_clock, duration> time_point;
	  //静态变量是属于类的变量, 是全局的.
      static constexpr bool is_steady = false;
	  //静态函数是属于类的函数. 恰似普通的函数, 执行不使用this指针,有3个
	  //成员函数 now() to_time_t(time_point &t), from_time_t(std::time_t t)
      static time_point now() noexcept;
      static std::time_t
      to_time_t(const time_point& __t) noexcept
      {
 return std::time_t(duration_cast<chrono::seconds>
      (__t.time_since_epoch()).count());
      }

      static time_point
      from_time_t(std::time_t __t) noexcept
      {
 typedef chrono::time_point<system_clock, seconds> __from;
 return time_point_cast<system_clock::duration>
        (__from(chrono::seconds(__t)));
      }
    };

now 是system_clock 类的静态成员函数, 返回一个time_point 类型对象

2.1.2 什么是 chrono::time_point?

看一下它的声明,

template<class Clock, class Duration = typename Clock::duration> class time_point;

它是一个类模板. 有两个类型参数.

时钟类型决定了时间的来源, 有system_clock, steady_clock,high_resolution_clock(是system_clock的代名词)

system_clock, 前面已经有交代.

剧透一下 system_clock 的纪元为 1970-01-01 00:00:00 UTC), unix时间戳起点

system_clock是time_point类模板的第一个参数.

time_point类模板的第二个参数类型duration 是什么?

2.1.3 什么是duration?

duration 是一个类型,这里先给duration的一个实例.

2.1.3.1 duration 的一个实例
cpp 复制代码
(gdb) ptype dur_obj
type = struct std::chrono::duration<double, std::ratio<1, 1000> > [with _Rep = double, _Period = std::ratio<1, 1000>] {
  private:
    _Rep __r;

  public:
    duration(void);
    duration(const std::chrono::duration<_Rep, _Period> &);
    ~duration();
    std::chrono::duration<_Rep, _Period> & operator=(const std::chrono::duration<_Rep, _Period> &);
    _Rep count(void) const;
    std::chrono::duration<_Rep, _Period> operator+(void) const;
    std::chrono::duration<_Rep, _Period> operator-(void) const;
    std::chrono::duration<_Rep, _Period> & operator++(void);
    std::chrono::duration<_Rep, _Period> operator++(int);
    std::chrono::duration<_Rep, _Period> & operator--(void);
    std::chrono::duration<_Rep, _Period> operator--(int);
    std::chrono::duration<_Rep, _Period> & operator+=(const std::chrono::duration<_Rep, _Period> &);
    std::chrono::duration<_Rep, _Period> & operator-=(const std::chrono::duration<_Rep, _Period> &);
    std::chrono::duration<_Rep, _Period> & operator*=(const _Rep &);
    std::chrono::duration<_Rep, _Period> & operator/=(const _Rep &);
    static std::chrono::duration<_Rep, _Period> zero(void);
    static std::chrono::duration<_Rep, _Period> min(void);
    static std::chrono::duration<_Rep, _Period> max(void);
    void duration<int>(const int &);
    void duration<double>(const _Rep &);
    void duration<long, std::ratio<1, 1000000000> >(const std::chrono::duration<long, std::ratio<1, 1000000000> > &);

    typedef _Rep rep;
}

它有一个私有成员变量 _Rep __r, __Rep 是represent的简写, 是类模板的第一个类型参数.可能是double或long

类模板还有第2个类型参数, 此处是 std::ratio<1,1000> 类型, 这个类型起码有2个类属性可以使用

std::ratio<1,1000>::num=1

std::ratio<1,1000>::den=1000

至于其它构造,析构,重载运算符就不具体分析了.

2.1.4 这么多的内涵,到底怎样理解time_point呢?

时间点对象timepoint是时间点类模板用system_clock 和 nanoseconds 为类型参数实例化后的一个对象.它有一个duration类型的变量记录其属性

其值说明是从 1970-01-01 00:00:00 开始的 纳秒数, 用long int 表示的数

2.1.5 time_point t1 在gdb中的表示

time_point 包含一个duration 对象 __d, duration对象包含一个实现类型(long或double)变量 __r

(gdb) p t1

$1 = {

__d = {

__r = 1747640811095678930 //1970-01-01 00:00:00开始的时间, 单位仅从对象本身是看不出来的.

}

}

//从类模板类型参数上知道它是ns, 但模板类型参数仅仅是编译期属性, 编译期知道它是ns, 但运行期就不知道了.

cpp 复制代码
(gdb) ptype t1 , 
type = struct std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long, std::ratio<1, 1000000000> > > [with _Clock = std::chrono::_V2::system_clock, _Dur = std::chrono::duration<long, std::ratio<1, 1000000000> >] {
  private:
    _Dur __d;  //私有成员变量, duration 类型

  public:
    time_point(void);
    time_point(const _Dur &);
    _Dur time_since_epoch(void) const;
    std::chrono::time_point<_Clock, _Dur> & operator+=(const _Dur &);
    std::chrono::time_point<_Clock, _Dur> & operator-=(const _Dur &);
    static std::chrono::time_point<_Clock, _Dur> min(void);
    static std::chrono::time_point<_Clock, _Dur> max(void);

    typedef _Dur duration;
}


(gdb) p t2
$2 = {
  __d = {
    __r = 1747640813823889979 //unix 时间点到现在的时间间隔
  }
}

2.2 auto delta_t = t2 - t1;

//两个时间点之差是duration 变量

//2个time_point 对象相减,运算被重构了. 返回的是 duration 对象

(gdb) p delta_t //一种duration 对象

$3 = {

__r = 2728211049

}

(gdb) p dur_obj //另一种duration 对象

$4 = {

__r = 2728.211049

}

2.3 auto dur_obj = std::chrono::duration<double, std::milli>(delta_t);

代码分析:

std::chrono namespace

duration<double, std::milli>: 是一个实例化模板类

std::chrono::duration<double,std::milli>(delta_t);

类名称后面跟上一个参数(这里是duration为参数)就是构建对象的过程(copy构造)

auto dur_obj = std::chrono::duration<double, std::milli>(delta_t); (赋值构造)

把一个无名对象赋值给一个有名对象 dur_obj

duration 对象是什么?数值代表了什么意思?

请参考2.1.4 说明duration 对象是什么类型

2.3.1 duration 对象能够知道数值代表的是毫秒,纳秒或者其它单位吗?

答: 对于一个duration 对象

$4 = {

__r = 2728.211049

}

duration 本身并不知道数值代表的是ms,ns或其它单位.

但是duration类却能够根据构造函数传来的类型及模板参使用的类型对传来的数值进行转换.

这是静态编译的能力.

现在已经计算出了这个值并付给了对象的成员. 但这个对象已经不知道自己是什么单位了,

因为对象本身没有保留单位信息. 即单位信息做为模板类型参数不是运行期特性只是编译期特性.

那我们怎么知道数值的单位是什么呢?

这是你自己的问题, 你自己根据数值的转变过程确定它应该是什么单位.

相关推荐
zfj3214 个月前
JMeter线程组Duration和循环次数设置冲突后,Duration优先级高
jmeter·duration·循环次数·线程组·持续时间
许野平6 个月前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
赢乐9 个月前
鸿蒙HarmonyOS开发:如何灵活运用动画效果提升用户体验
harmonyos·transition·duration·显式动画 animateto·属性动画 animation·animateparam·布局更新动画
Black.Spider1 年前
C++计算程序运行时间
c++·chrono
会编程的大白熊1 年前
rust - 常用时间处理
rust·chrono
凡夫贩夫1 年前
深入了解Java Duration类,对时间的精细操作
java·后端·java8新特性·日期时间api·localdatetime·period·duration