简介
- 所有标准库类和函数都在std名称空间或其子名称空间中声明
- C++标准库的核心是泛型容器和泛型算法。该库中的这个子集通常程序标准模板库(Standard Template Library, STL),因为它最初基于第三方库“标准模板库”,该库大量使用了模板。
<string>
– 字符串 [ok]
- C++20包括了一个强大的类型安全的字符串格式化库,可以通过定义在
<format>
头文件中的std::format()
进行访问
<regex>
– 正则表达式[ok]
<fstream>
– I/O流[ok]
- 大多数的I/O功能在如下几个头文件中定义:
<fstream>
<iomanip>
<ios>
<iosfwd>
<iostream>
<istream>
<ostream>
<sstream>
<streambuf>
<strstream>
<iomanip>
resetiosflags()
- 简述:清除指定的 ios_base 标志
setiosflags()
- 简述:设置指定的 ios_base 标志
setbase()
- 简述:更改用于整数 I/O 的基数
setfill()
- 简述:更改填充字符
setprecision()
- 简述:更改浮点精度
setw()
- 简述:更改下个输入/输出域的宽度
get_money()
- 简述:剖析货币值
put_money()
- 简述:格式化并输出货币值
get_time()
- 简述:剖析指定格式的日期/时间值
put_time()
- 简述:按照指定格式格式化并输出日期/时间值
- 声明:
template<class CharT> put_time(const std::tm* tmb, const CharT* fmt);
- 参数:
tmb
– 指向从 std::localtime 或 std::gmtime 获得的日历时间结构体的指针fmt
– 指向指定转换格式的空终止 CharT 串的指针,具体参考:https://zh.cppreference.com/w/cpp/io/manip/put_time
(默认使用%c %Z
)
quoted()
- 简述:插入和读取带有内嵌空格的被引号括起来的字符串
<memory>
– 智能指针[ok]
- 编写健壮程序时,需要面对的一个问题就是要知道何时删除对象。
- 有几种可能发生的故障:
- 根本没有删除对象(没有释放内存),这称为内存泄漏(memory leaks)。
- 一段代码删除了内存,而另一段代码仍然引用了这个内存,导致直线那个内存的指针不再可用或已重新分配作他用,这称为悬空指针(dangling pointer)
- 一段代码释放了内存,而另一端代码试图释放同一块内存,这称为双重释放(double deletion)
<exception>
– 异常[ok]
- 大多数异常支持在下面几个头文件中定义:
<exception>
<stdexcept>
<system_error>
<cmath>
– 数学工具
- 数学工具类和函数
<chrono>
– 时间和日期工具[ok]
- 简述:在C++11的日期时间库中,共有3个概念,分别是持续时间(Duration)、时间点(timepoint)、时钟(clock)。
Clocks
定义中的时钟主要有3个,分别是:
- system_clock,顾名思义,就是系统时钟,他一般是unix时间,即从1970年1月1日到现在的间隔。如果系统时间发生调整,那么调用该方法获取的时间值也会跟着变化。
- steady_clock,是单调时间,即每后一次调用都一定会比前一次调用的时间要晚,它并不反映真实的世界时间。在内部的实现中,有可能是系统开启以来的时间。通过该时钟很适合用来获取一段时间内的间隔,它不随系统时间改变而改变
- high_resolution_clock,高精度时间,用来测量细微间隔的一段时间,它的内部实现中可能是system_clock或是steady_clock,也可能是其他独立的时间。
一般来说,我们使用的都是system_clock
system_clock的主要方法有3个,分别是
- now,用来获取当前时间。
- to_time_t,用来将系统时间转变为std::time_t类型。
- from_time_t,用来将std::time_t类型转换为系统时间点
使用system_clock获取当前系统时间。
1
2
3
4
5
6
7
8
9
int main() {
auto time = std::chrono::system_clock::now();
auto tt = std::chrono::system_clock::to_time_t(time);
std::cout << std::put_time(std::localtime(&tt), "%Y-%m-%d %H:%M:%S") << std::endl;
return 0;
}统计函数的执行耗时,这种情况更适合使用steady_clock。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
long fibonacci(unsigned n)
{
if (n < 2) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
int main()
{
auto start = std::chrono::steady_clock::now();
std::cout << "f(42) = " << fibonacci(42) << '\n';
auto end = std::chrono::steady_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n";
}
```
### Duration
+ 持续时间表示一个时间段,比如1s、1min、1day等等,这些时间段是有单位的,因此持续时间也是一个模板变量,用来指定不同的单位
+ 它的定义如下:
```cpp
// Rep表示单位的数量单位
// Period表示单位
template<class Rep, class Period = std::ratio<1>> class duration;Period用来表示时间的单位,比如秒、天、小时等等,而Rep则表示容纳某个数量时间的单位。比较绕口,举个例子,比如说10天,那么Period是单位day,那么其数量是10,而10的类型可以是int型,也可以short型,Rep就用来表示这到底是什么类型存储这个量,如果类型过小,如果时间太长的话将会导致溢出。
再来看下Period的定义,
1
2
3// Num,表示分子
// Denom,表示分母
template<std::intmax_t Num, std::intmax_t Denom = 1> class ratio;举个简单点的例子,Num为1,Denom也为1时,表示是1s,如果Num为1,Denom为1000,那么相当于是1/1000s,也即毫秒。如果Num为60,Denom为1,那么表示 60 / 1s,也即相当于1min。
下面是chrono头文件中的一些常见持续时间定义。
1
2
3
4
5
6
7
8
9
10
11Type Definition
std::chrono::nanoseconds duration</*signed integer type of at least 64 bits*/, std::nano>
std::chrono::microseconds duration</*signed integer type of at least 55 bits*/, std::micro>
std::chrono::milliseconds duration</*signed integer type of at least 45 bits*/, std::milli>
std::chrono::seconds duration</*signed integer type of at least 35 bits*/>
std::chrono::minutes duration</*signed integer type of at least 29 bits*/, std::ratio<60>>
std::chrono::hours duration</*signed integer type of at least 23 bits*/, std::ratio<3600>>
std::chrono::days (since C++20) duration</*signed integer type of at least 25 bits*/, std::ratio<86400>>
std::chrono::weeks (since C++20) duration</*signed integer type of at least 22 bits*/, std::ratio<604800>>
std::chrono::months (since C++20) duration</*signed integer type of at least 20 bits*/, std::ratio<2629746>>
std::chrono::years (since C++20) duration</*signed integer type of at least 17 bits*/, std::ratio<31556952>>针对Duraion来说,一般有两种操作,
- 时间的增减。
- 不同持续时间单位之间的转换。
Duration重载了+/-运算符,可以直接进行+/-操作,类型之间的转换可以使用duration_cast方法。
下面是一些使用实例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main() {
std::chrono::milliseconds ms(3);
printf("%lld\n", ms.count());
using second = std::chrono::duration<double>;
auto s = std::chrono::duration_cast<second>(ms);
printf("%llf\n", s.count());
std::chrono::seconds sec(10);
auto du = sec + ms;
printf("%lld\n", du.count());
return 0;
}
TimePoint
从时钟拿到的时间是时间点,它代表了时间段上的一个点,比如2019年10月21日10:20:10。
时间点的定义如下。
template<class Clock, class Duration = typename Clock::duration> class time_point;
通过time_point的模板参数,我们可以看到,一个是时钟,另外一个是持续时间,实际上timepoint就是一个时钟的基准时间加上一个时间段
对于时间点来说,下面这几个方法比较重要。
- time_since_epoch,获取以模板时钟的起始时间到现在的这个持续时间
- time_point_cast,用来将时间点转换为基于同一个时钟,但不同类型持续时间的时间点。
- 时间点也重载了+/-运算符,用来进行两个时间点之间的相加减
下面是一些使用示例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main() {
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
std::chrono::minutes m(20);
std::chrono::time_point<std::chrono::system_clock> then = now + m;
std::time_t tt = std::chrono::system_clock::to_time_t(then);
std::cout << "timestamp is : " << now.time_since_epoch().count() << std::endl;
std::cout << std::put_time(std::localtime(&tt), "%F %T") << std::endl;
// 降低时间精度,默认system_clock的duration精度是 1/10 micro sec
auto then_min = std::chrono::time_point_cast<std::chrono::minutes>(then);
tt = std::chrono::system_clock::to_time_t(then_min);
std::cout << std::put_time(std::localtime(&tt), "%F %T") << std::endl;
return 0;
}
一些应用
获取时间戳。
1
2
3
4
5
6
7
8std::time_t getTimeStamp()
{
std::chrono::time_point<std::chrono::system_clock,std::chrono::milliseconds> tp = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
auto tmp=std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch());
std::time_t timestamp = tmp.count();
//std::time_t timestamp = std::chrono::system_clock::to_time_t(tp);
return timestamp;
}将时间戳转为日期。
1
2
3
4
5
6
7
8
9
10std::tm* gettm(int64 timestamp)
{
int64 milli = timestamp+ (int64)8*60*60*1000;//此处转化为东八区北京时间,如果是其它时区需要按需求修改
auto mTime = std::chrono::milliseconds(milli);
auto tp=std::chrono::time_point<std::chrono::system_clock,std::chrono::milliseconds>(mTime);
auto tt = std::chrono::system_clock::to_time_t(tp);
std::tm* now = std::gmtime(&tt);
printf("%4d年%02d月%02d日 %02d:%02d:%02d\n",now->tm_year+1900,now->tm_mon+1,now->tm_mday,now->tm_hour,now->tm_min,now->tm_sec);
return now;
}在上面的程序中,时间精度只到秒,这是time_t结构的限制,如果希望获取到ms精度,那么直接使用timestamp % 1000的方式就行。
<random>
– 随机数[ok]
- 随机数库,带有随机数引擎,随机数引擎适配器以及随机数分布。
- 通过这些组件可以生成更适合特定问题的随机数,例如正态分布,负指数分布等
<initializer_list>
– 初始化列表
- 它们便于编写参数数目可变的函数
<utility>
– pair
- 它定义了pair类模板,用于存储两种不同类型的元素。这称为存储异构元素
- pair允许在一个对象中保存类型毫不相关的元素
<tuple>
– tuple
- 它定义的tuple是pair的一种泛化,它是固定大小的序列,元组的元素可以是异构的,tuple实例化的元素数目和类型在编译器是固定不变的。
词汇类型(vocabulary type)
<optional>
- 要么存储指定类型的值,要么什么都不存储
<variant>
- 可存储单个值(属于一组给定类型中的一种类型)
<any>
- 可包含单个值,值可以是任何类型
<functional>
– 函数对象
在
<functional>
中定义的std::function
函数模板是一个多态函数包装器,可以用来创建指向任何可调用对象的类型,例如函数,函数对象或者lambda表达式std::function
的示例可以用作函数指针,也可以用作函数实现回调的参数,可以存储,赋值,移动,也可以执行函数模板的模板参数看起来和大多数模板参数有些不同,语法如下:
std::function<R(ArgTypes...)>
详解:
R
: 是函数的返回类型ArgTypes
: 是函数参数类型的逗号分隔列表
实现函数调用运算符的类称为函数对象(function object)
函数对象可用作某些标准库算法的谓词
<filesystem>
– 文件系统
<thread>
– 多线程[ok]
<type_traits>
– 类型萃取
<cstdint>
– 标准整数类型
- 它定义了大量标准整数类型,例如int8_t 和 int64_t 等,还包含了多个宏(指定这些类型的最小值和最大值)
<version>
– 相关实现信息[ok]
- 它可用于查询正在使用的C++标准库的相关实现信息
- 版本号
- 发布日期
- 版权声明
<source_location>
– 源位置
- C++20添加了
std::source_location
类,用来查询有关源代码的信息,例如文件名,函数名,行号和列号,并可用于替换旧的C风格宏__FILE__
和__LINE__
容器
<vector>
[ok]
<list>
<forward_list>
<deque>
<array>
<span>
<queue>
<stack>
<set>
<map>
<alogrithm>
– 算法[ok]
<ranges>
– 范围库
- C++20引入了范围库,这使得处理元素序列变得更加简单和优雅