StringPiece
在 StringPiece.h
文件中,声明了两个类类型,一个是 StringArg
,另一个是 StringPiece
,前者用于在传递函数参数时同时兼容 C 风格的字符串(const char*)和 C++ 风格的字符串(std::string)。而后者则可用于构建同时兼任这两种风格字符串的实例对象。
如果函数参数使用 const std::string&
作为形参,尽管可以同时兼容两种风格的字符串,但是当传入一个很长的 char*
时,会生成一个很大的 string 对象,其开销较大。而且使用 std::string
时不可避免会带来很多不必要的拷贝,拷贝多了必然影响性能。因此在很多高性能 C++ 框架的实现中,都会使用 StringPiece
作为 std::string
类型的 wrapper
,该类只持有目标字符串的指针,而避免额外的拷贝,同时也保证了兼容性。当仅仅读取字符串的值,可以使用该类型。
常见的实现如下:
因为 StringPiece 不控制字符串的声明周期,因此调用方要保证在 StringPiece 的生命周期内,其指向的字符串是始终有效的。
如果想使用 StringPiece 作为 hash 的 key,需要自定义哈希函数,可以参考 Chromium 实现。
由于 StringPiece 只持有目标指针,所以为 POD(Plain Old Data)
类型,同时拥有 trival
构造函数,因此可以定义 __type_traits
以指示 STL 采用更为高效的算法实现。
如果至少满足下面 3 条中的一条,则该类类型中含有 non-trival 函数:
- 显示定义了 ctor、copy、assignment、dtor;
- 类中具有非静态非 POD 类型的数据成员;
- 有基类;
例如:
// 没有显式定义 ctor、copy、assignment、dtor 所以均为 trival
class T1 {
int a; // POD类型
};
// 没有显式定义 copy、assignment、dtor 所以均为 trival
class T2 {
T1() {} // 显示定义 ctor,为 non-trival ctor
int a; // POD
std::string b; // 非POD
};
如果某个类中都是 trival ctor/dtor/copy/assignment 函数,对这个类进行构造、析构、拷贝、赋值时可以采用最有效率的方法,即直接采用内存操作,例如 malloc()
、memcpy()
等以提高性能。
因此使用 __type_traits
对于 StringPiece 来说,在使用 STL 容器时,可以让其析构函数什么都不做,提高程序效率。
而在 C++ 11
中,有了 =delete
和 =default
关键字,如果使用这两个关键字,那么该函数就为 trival 类型,编译器会为其做出进一步优化。相对于空函数体而言,则更具有优势。
对于如下测试代码:
#include <iostream>
#include <vector>
using namespace std;
class TestA {
public:
TestA() {}
~TestA() {}
private:
int a;
};
class TestB {
public:
TestB() = default;
~TestB() = default;
private:
int a;
};
#define CLASS_NUM 10000000
int main() {
clock_t start, end;
start = clock();
TestA* a = new TestA[CLASS_NUM];
delete[] a;
end = clock();
cout << "non-trival: " << (double)(end - start) / CLOCKS_PER_SEC << endl;
start = clock();
TestB* b = new TestB[CLASS_NUM];
delete[] b;
end = clock();
cout << "trival: " << (double)(end - start) / CLOCKS_PER_SEC << endl;
return 0;
}
两个类类型中都只含有一个 POD 类型 int,分别在堆上生成 1000 0000 个对象,然后进行销毁,所耗费的时间如下:
non-trival: 0.205
trival: 0.025
时间相关
Timestamp
Timestamp.h
文件中声明了时间戳相关的类类型 Timestamp
。它继承自三个父类:
class Timestamp : public muduo::copyable,
public boost::equality_comparable<Timestamp>,
public boost::less_than_comparable<Timestamp>
其中,muduo::copyable
表明该类可生成拷贝构造函数和赋值构造函数,boost::equality_compareable
和 boost::less_than_comparable
则用于快速重载比较运算符。
该类类型用于生成程序运行过程中的时间戳,例如 "2022-01-01 12:56:47:01.000000",它使用 UTC 时间来进行计算,精度为微秒。
在 Linux 下,有如下几个获取时间的函数:
time(2)
: 返回自公元1970年1月1日的UTC时间,从0时0分0秒算起到现在所经过的秒数;ftime(3)
: 已废弃;clock_gettime(2)
: 精度高,系统开销大;gettimeofday(2)
: 精度达到微秒,系统开销较小,适用于网络编程
类中仅有一个成员变量 microSecondsSinceEpoch_
用来表示自 Epoch 时间起到现在所经过的微秒数,用初始值 0 来表述无效值。
类中含有一个无参构造函数和静态函数 invalid()
可以返回一个无效的时间戳对象,用于特殊应用。
如果我们使用 time(2)
获取了自 Epoch 以来的时间(精度为秒),可以使用 fromUnixTime()
重载函数返回一个 Timestamp 对象。
通过 microSecondsSinceEpoch()
和 secondsSinceEpoch()
函数可以分别获得自 Epoch 以来的微秒数和秒数。
函数 toString()
则用于将秒数、微秒数转换为 std::string
类型,在其实现中,使用到了 PRId64
关键字,它的目的是为了同时支持 32 位系统和 64 位系统。在 32 位系统中表示为 long long int
,在 64 位系统中则表示为 long int
。
而函数 toFormattedString()
函数则用于将时间戳转换为人类可以理解的格式化后的字符串形式,格式化后的形式为 "yyyymmdd hh:mm:ss.zzzzzz"。
TimeZone
TimeZone
类是为了方便时区之间和时令之间的转换。
Date
Date.h
文件定义了类类型 Date
,用于表示格里高利历,即常说的公历。
类内部只有一个成员变量 julianDayNumber_
,它指的是儒略日,即自公元前 4713 年 1 月 1 日到现在所经过的具体的天数。
类内部定义了结构体 YearMonthDay
,用来存储年、月、日:
struct YearMonthDay {
int year; // [1900..2500]
int month; // [1..12]
int day; // [1..31]
};
标签:std,Muduo,函数,int,StringPiece,Time,trival,string
From: https://www.cnblogs.com/tuilk/p/16791395.html