muduo网络库学习笔记(1):Timestamp类

来源:互联网 发布:一起作业网刷学豆软件 编辑:程序博客网 时间:2024/06/07 10:59

时间戳一般用来唯一地标识某一刻的时间,通常是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总毫秒数。

muduo网络库对时间戳Timestamp类也进行了封装。

Timestamp类类图:
这里写图片描述

由类图可知,Timestamp类的参数有一个常量kMicroSecondsPerSecond表示每秒所对应的微秒数,成员变量microSecondsSinceEpoch_表示到1970-01-01 00:00:00 UTC的微秒数。成员函数包括swap()交换操作,toString()、toFormattedString()将时间转换为string类型或指定格式,valid()判断Timestamp是否有效,invalid()返回一个无效的Timestamp,now()返回当前时间的Timestamp,secondsSinceEpoch()/microSecondsSinceEpoch()返回到1970-01-01 00:00:00 UTC的秒数/微秒数。

代码中的一些要点如下:
(1)Timestamp类继承自boost::less_than_comparable <T>模板类
只要实现 <,即可自动实现>,<=,>=

(2)使用到了BOOST_STATIC_ASSERT,编译时断言
我们一般使用的assert是运行时断言,用一个小例子来理解BOOST_STATIC_ASSERT:

#include <boost/static_assert.hpp>class Timestamp{private:     int64_t microSecondsSinceEpoch_;};// 编译时断言通过// BOOST_STATIC_ASSERT(sizeof(Timestamp) == sizeof(int64_t));// 编译时断言失败BOOST_STATIC_ASSERT(sizeof(int) == sizeof(short));int main(void){    return 0;}

编译上述例子,在编译时就会报错
这里写图片描述

(3)gmtime和gmtime_r函数
用法:
struct tm *gmtime(const time_t *timep);
struct tm *gmtime_r(const time_t *timep, struct tm *result);

gmtime(线程不安全的)是把日期和时间转换为格林威治(GMT)时间的函数。将参数timep 所指的time_t 结构中的信息转换成真实世界所使用的时间日期表示方法,然后将结果由结构tm返回。使用gmtime后要立即处理结果,否则返回的指针指向的内容可能会被覆盖。一个好的方法是使用gmtime_r(线程安全的),gmtime_r()函数功能与此相同,但是它可以将数据存储到用户提供的结构体中,由于使用了用户分配的内存,是不会出错的。

节选muduo源码中的使用示例:

string Timestamp::toFormattedString() const{  char buf[32] = {0};  time_t seconds = static_cast<time_t>(microSecondsSinceEpoch_ / kMicroSecondsPerSecond);  // 秒数  int microseconds = static_cast<int>(microSecondsSinceEpoch_ % kMicroSecondsPerSecond);  struct tm tm_time;  // 微秒数  // 把time_t结构中的信息转换成真实世界所使用的时间日期,存储在tm_time结构中  gmtime_r(&seconds, &tm_time);  // 格式化输出时间戳  snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d.%06d",      tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,      tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec,      microseconds);  return buf;}

(4)使用PRId64
int64_t用来表示64位整数,在32位系统中是long long int,在64位系统中是long int,所以打印int64_t的格式化方法是:

printf(“%ld”, value);  // 64bit OSprintf("%lld", value); // 32bit OS

这种做法是不可移植的。

跨平台的做法:

// C++使用PRID64,需要两步:// 包含头文件:<inttypes.h>// 定义宏:__STDC_FORMAT_MACROS,可以通过编译时加-D__STDC_FORMAT_MACROS,或者在包含文件之前定义这个宏。#define __STDC_FORMAT_MACROS#include <inttypes.h>#undef __STDC_FORMAT_MACROS printf("%" PRId64 "\n", value);  

(5)对象语义和值语义

值语义:值语义是指对象的拷贝与原对象无关,拷贝之后就与原对象脱离关系,彼此独立互不影响(深拷贝)。C++中的内置类型都是值语义,比如说int。值语义的一个巨大好处是生命期管理很简单。

对象语义:对象语义指的是面向对象意义下的对象。
对象拷贝要么是禁止的(Noncopyable) ,要么一个对象被系统标准的复制方式复制后,与被复制的对象之间依然共享底层资源,对任何一个的改变都将改变另一个(浅拷贝)。比如,Thread 是对象语义,拷贝 Thread 是无意义的,也是被禁止的:因为 Thread 代表线程,拷贝一个Thread对象并不能让系统增加一个一模一样的线程。

对象语义对象生命期不容易控制,一般通过智能指针来解决。智能指针实际上是将对象语义转化为值语义,利用局部对象(智能指针)的确定性析构,智能指针包括auto_ptr, shared_ptr, weak_ptr, scoped_ptr。

0 0
原创粉丝点击