打开主菜单

w:C++程序设计语言中,chronow:标准模板库(STL)中与时间有关的头文件(自w:C++11开始)。该头文件中所有函数与类模板均定义在std::chronow:命名空间中。

目录

概念编辑

  • duration:时间长度,如1分钟、2小时、10毫秒等。表示为类模板duration的对象,用一个count representation与一个period precision表示。例如,10毫秒的10为count representation,毫秒为period precision。
  • time points:表示一个时间点。例如某人的生日、今天的日出时间等。表示为类模板time_point的对象。用相对于一个固定时间点epoch的duration来表示。
  • clocks:时间点相对于真实物理时间的框架。至少提供了3个clock:system_clock,steady_clock,high_resolution_clock

类模板编辑

时间长度duration编辑

表示time span。该类模板声明为:

 template <class Rep, class Period=ratio<1> > class duration;

第一个模板参数为存储时间计数的数据类型。成员函数count()返回该计数。第二个模板参数表示计数的一个周期,一般是std::ratio类型,表示一个周期(即一个时间嘀嗒tick)是w:秒钟的倍数或分数,在w:编译时应为一个w:有理数常量。

duration模板类实例化typedef:

类型 Rep Period
hours signed integral至少23比特 ratio<3600,1>
minutes signed integral至少29比特 ratio<60,1>
seconds signed integral至少35比特 ratio<1,1>
miliseconds signed integral至少45比特 ratio<1,1000>
microseconds signed integral至少55比特 ratio<1,1000000>
nanoseconds signed integral至少64比特 ratio<1,1000000000>
rep 对应于模板的第1个参数
period 对应于模板的第2个参数

chrono提供的预定义的时间长度单位都是int64类型的内部存储数据

  • duration模板类成员函数:
    • 构造函数
    • 析构函数
    • count 返回时间嘀嗒计数
    • zero: 静态函数,表示0值
    • min:静态函数,表示最小可能值
    • max:静态函数,表示最大可能值
    • operator= 赋值运算符
    • operator+ 酉运算符
    • operator- 酉运算符
    • operator++ 前缀++
    • operator++(int) 后缀++
    • operator-- 前缀--
    • operator--(int) 后缀--
    • operator+=
    • operator-=
    • operator*=
    • operator/=
    • operator%=
  • 非成员函数
    • std::common_type<std::chrono::duration> 是类模板std::common_type的特化版本
    • operator+
    • operator-
    • operator*
    • operator/
    • operator%
    • operator==
    • operator!=
    • operator<
    • operator<=
    • operator>
    • operator>=
    • duration_cast 把时间长度转换到不同时间嘀嗒单位的另一个时间长度。
    • floor(std::chrono::duration) w:C++17 转换时间长度向下近似
    • ceil(std::chrono::duration) w:C++17 转换时间长度向上近似
    • round(std::chrono::duration) w:C++17 转换时间长度向最近偶数近似
    • abs(std::chrono::duration) w:C++17 时间长度的绝对值
  • 帮助类Helper classes
    • treat_as_floating_point 表示一个时间长度可转换为不同的时间嘀嗒单位
    • duration_values 构造给定类型的事件嘀嗒计数的零值、最小值、最大值

w:C++14标准定义的字面量编辑

主条目:w:用户定义字面量

均定义在std::literals::chrono_literals命名空间中。因此需要先声明using namespace std::chrono_literals;

  • operator""h
  • operator""min
  • operator""s
  • operator""ms
  • operator""us
  • operator""ns

例子编辑

为了区分秒数和普通的数值之间的差异,seconds类在设计的时候就禁止了数值隐式转换为seconds类

seconds s = 3;  // 编译出错
seconds s1{3};  // 这样是可以的
s1 = 4; // 编译出错

std::cout << s << "\n"; // 目前还不可以
std::cout << s.count() << "s\n"; // 这样是可以的

seconds s2 = 3s;    // C++14支持字面常量
seconds s3 = s2 + s1;   // 支持基本的算术操作,但是不支持seconds和一个普通数值进行算术操作

seconds::min(); // 获取秒类型可以表示的范围,
seconds::max();

minutes m1{2};
seconds s2 = m1;        // m1隐式转换为seconds
seconds s3 = s2 + m1;   // m1隐式转换为seconds,然后运算 

//不同时间长度单位的隐式转换必须是向下转换,如minutes转seconds。如果向上转换需用duration_cast显式转换。因为这些转换是截断近似,而不是四舍五入。
seconds s2{1000};
minutes m3 = std::chrono::duration_cast<minutes>(s2);

时间点time_point编辑

表示一个时间点,即一个时刻的值。它存储为从一个固定时刻(epoch)开始的一段时间的长度(duration)。chrono库中采用的是Unix的时间戳1970年1月1日 00:00。时间点的类模板形如:

template <class Clock,
          class Duration = typename Clock::duration>
class time_point {
    Duration d_;
public:
    using clock    = Clock;
    using duration = Duration;
    // ...  
};
  • 类型定义
    • clock 使用的时钟
    • duration 一个std::chrono::duration类型,用于度量从固定时刻开始的时间的长度
    • rep 算术类型,表示时间长度的嘀嗒(tick)数
    • period 一个std::ratio类型,表示一个时间嘀嗒的单位
  • 成员函数
    • (constructor)
    • time_since_epoch 返回从固定时刻开始的时间长度。
    • operator+= 修改时间长度
    • operator-= 修改时间长度
    • min 静态成员函数,最小可能的时间长度
    • max 静态成员函数,最大可能的时间长度
  • 非成员函数
    • std::common_type<std::chrono::time_point> 是类模板std::common_type的特化版本
    • operator+ 修改时间长度
    • operator- 修改时间长度
    • operator== 比较时间点
    • operator!= 比较时间点
    • operator< 比较时间点
    • operator<= 比较时间点
    • operator> 比较时间点
    • operator>= 比较时间点
    • time_point_cast 函数模板,在同一时钟下把一个时间点转化为具有不同时钟滴答长度的另一个时间点
    • floor(std::chrono::time_point) w:C++17 函数模板 转化时间点并向下近似
    • ceil(std::chrono::time_point) w:C++17 函数模板 转化时间点并向上近似
    • round(std::chrono::time_point) w:C++17 函数模板 转化时间点并近似到最近邻的偶数

不同类型的时间点之间也可以相互转换,可隐式的向下转换;如果向上转换就必须显式的使用time_point_cast:

 using namespace std::chrono;
  template <class D> using sys_time = time_point<system_clock, D>;
  sys_time<seconds> tp{5s};            // 5s
  sys_time<milliseconds> tp2 = tp;     // 5000ms  隐式的向下转换
  tp = time_point_cast<seconds>(tp2);  // 5s  向下转换,需要显示的使用time_point_cast

时钟clock编辑

语言标准预定义的3个时钟,形如:

struct some_clock
{
    using duration = chrono::duration<int64_t, microseconds>;
    using rep = duration::rep;
    using period = duration::period;
    using time_point = chrono::time_point<some_clock>; 
    static constexpr bool is_steady = false; 
     static time_point now() noexcept;
};

不同时钟的时间点无法相互转换:

system_clock::time_point tp = system_clock::now();
steady_clock::time_point tp2 = tp;  // no viable conversion

Visual C++ 2015把steady_clock都用QueryPerformanceCounter实现;把high_resolution_clock定义为steady_clock的别名。

system_clock编辑

当前系统范围(即对各进程都一致)的一个实时的日历时钟(wall clock)。但是这个值并不一定是单调的,因为操作系统可能会修改时间,导致system_clock返回的时间不单调。

  • 成员类型:
    • rep 表示时钟滴答计数的算术类型
    • period 表示时钟滴答长度的std::ratio类型,以秒钟为单位长度
    • duration std::chrono::duration<rep, period>
    • time_point std::chrono::time_point<std::chrono::high_resolution_clock>
  • 成员常量:
    • constexpr bool is_steady (public static member constant) 表示该时钟的每个时间嘀嗒单位是否为均匀(即长度相等) 。
  • 成员函数
    • now 静态函数 返回时钟的当前值,类型为std::chrono::time_point
    • to_time_t 静态函数 把系统时钟的时间点转化为C风格的std::time_t
    • from_time_t 静态函数 把C风格的std::time_t转化为系统时钟的时间点

steady_clock编辑

当前系统实现的一个稳定时钟。表示的是单调时钟,随着物理时间向前,这个时钟的时间点不会减少,最适合进行间隔的测量。

  • 成员类型:
    • rep 表示时钟滴答计数的算术类型
    • period 表示时钟滴答长度的std::ratio类型,以秒钟为单位长度
    • duration std::chrono::duration<rep, period>
    • time_point std::chrono::time_point<std::chrono::high_resolution_clock>
  • 成员常量:
    • constexpr bool is_steady (public static member constant) 表示该时钟的每个时间嘀嗒单位是否为均匀(即长度相等) 。该值总为true
  • 成员函数
    • now 静态函数 返回时钟的当前值,类型为std::chrono::time_point

high_resolution_clock编辑

当前系统实现的一个高分辨率时钟。

  • 成员类型:
    • rep 表示时钟滴答计数的算术类型
    • period 表示时钟滴答长度的std::ratio类型,以秒钟为单位长度
    • duration std::chrono::duration<rep, period>
    • time_point std::chrono::time_point<std::chrono::high_resolution_clock>
  • 成员常量:
    • constexpr bool is_steady (静态) 表示该时钟的每个时间嘀嗒单位是否为均匀(即长度相等)
  • 成员函数
    • now 静态函数 返回时钟的当前值,类型为std::chrono::time_point

表示为字符串的示例编辑

#include <iostream>
#include <chrono> 
#include <ratio>
#include <time.h>
#include <iomanip>
#include <sstream>
#include <string>
int main()
{ 

	using namespace std::chrono; 
	auto now = system_clock::now(); 
	time_t t = system_clock::to_time_t(now); 
	std::tm tm;
	localtime_s(&tm, &t);
	auto time = std::put_time(&tm, "%b %d %Y %H:%M:%S");
	std::cout << time << std::endl;
	std::stringstream ss;
	ss << time;
	std::string a{ ss.str() }; 
}

例子编辑

时间点的示例编辑

#include <iostream>
#include <iomanip>
#include <ctime>
#include <chrono>
 
int main()
{
    std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
    std::time_t now_c = std::chrono::system_clock::to_time_t(now - std::chrono::hours(24));
    std::cout << "24 hours ago, the time was "
              << std::put_time(std::localtime(&now_c), "%F %T") << '\n';
 
    std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
    std::cout << "Hello World\n";
    std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
    std::cout << "Printing took "
              << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count()
              << "us.\n";
}

时间长度的示例编辑

#include <iostream>
#include <chrono>
 
int main()
{
    using shakes = std::chrono::duration<int, std::ratio<1, 100000000>>;
    using jiffies = std::chrono::duration<int, std::centi>;
    using microfortnights = std::chrono::duration<float, std::ratio<12096,10000>>;
    using nanocenturies = std::chrono::duration<float, std::ratio<3155,1000>>;
 
    std::chrono::seconds sec(1);
 
    std::cout << "1 second is:\n";
 
    std::cout << std::chrono::duration_cast<shakes>(sec).count()
              << " shakes\n";
    std::cout << std::chrono::duration_cast<jiffies>(sec).count()
              << " jiffies\n";
    std::cout << microfortnights(sec).count() << " microfortnights\n";
    std::cout << nanocenturies(sec).count() << " nanocenturies\n";
}

综合示例编辑

#include <iostream>
#include <chrono>
#include <ctime>
 
long fibonacci(unsigned n)
{
    if (n < 2) return n;
    return fibonacci(n-1) + fibonacci(n-2);
}
 
int main()
{
    std::chrono::time_point<std::chrono::system_clock> start, end;
    start = std::chrono::system_clock::now();
    std::cout << "f(42) = " << fibonacci(42) << '\n';
    end = std::chrono::system_clock::now();
 
    std::chrono::duration<double> elapsed_seconds = end-start;
    std::time_t end_time = std::chrono::system_clock::to_time_t(end);
 
    std::cout << "finished computation at " << std::ctime(&end_time)
              << "elapsed time: " << elapsed_seconds.count() << "s\n";
}

参考文献编辑