1. <chrono>库
1)3个概念:
a. 时间段(Durations)
代表一个时间段。使用模板类duration表示。duration模板有两个参数:时间量(count representation)、时间单位(period precision)。例如,10ms的时间量为10,时间单位为毫秒。
b. 时间点(Time points)
代表一个时间点。使用类模板time_point表示。它使用从时钟起始时间(epoch,如Unix时间戳1970-01-01 00:00:00 UTC)计的时间段表示。它是一个固定的值,在不同的时钟上代表不同的时间。
c. 时钟(Clocks)
它是一个解释时间点的机制。有一个时间起点(epoch),时间点就是从该时间起点计的时间段。库中提供了至少3种时钟,分别是system_clock、steady_clock、high_resolution_clock。
时间点和时钟相互依赖,共同表示一个确定的时间。
2)常用预定义类型
名字 | 含义 |
hours | 时 |
minutes | 分 |
seconds | 秒 |
milliseconds | 毫秒 |
microseconds | 微秒 |
nanoseconds | 纳秒 |
示例:
#include<chrono>
// 10秒
std::chrono::seconds(10);
3)ratio
template <intmax_t N, intmax_t D = 1> class ratio;
模板实例表示一个分数形式的有理数,分子、分母是intmax_t类型。模板实例自身代表这个有理数,而不是模板实例的对象。模板实例只能被用做常量。
实例化后的模板像下面的样子:
// 1 / 3
struct ratio
{
static const intmax_t num = 1;
static const intmax_t den = 3;
};
4) duration
template <class Rep, class Period = ratio<1> >
class duration;
代表一个时间段。第一个参数为时间量的类型,第二个参数为时间单位的类型。时间量可以用count成员方法获取。时间单位是秒的比率。如
milliseconds ratio<1, 1000> // 1/1000秒
5)time_point
template <class Clock, class Duration = typename Clock::duration>
class time_point;
表示一个时间点。用以时钟的起始时间(epoch)计的一个时间段表示。使用成员函数time_from_epoch获取。
6)system_clock
获取当前时间的时钟。使用now成员函数返回当前时间。返回时间值得常用方法为:
std::chrono::system_clock::now().time_since_epoch().count();
参考:http://www.cplusplus.com/reference/chrono/
2. <random>库
1)mt19937
32位伪随机数生成器。是mersenne_twister_engine的实例。参考定义:
typedef mersenne_twister_engine<
uint_fast32_t,
32,
624,
397,
31,
0x9908b0df,
11,
0xffffffff,
7,
0x9d2c5680,
15,
0xefc60000,
18,
1812433253>
mt19937;
// example
// 已当前时间为随机种子创建生成器
#include <chrono>
#include <random>
#include <iostream>
std::mt19937 generator(std::chrono::system_clock::now().time_since_epoch().count());
std::cout << generator() << std::endl;
参考:http://www.cplusplus.com/reference/random/
3. <mutex>库
1)lock_guard
管理一个mutex,在对象创建时锁定mutex,在对象销毁时解锁mutex。是一个方便的作用域锁。
2)unique_lock
管理一个mutex,在对象创建时锁定mutex,在对象销毁时解锁mutex。
3)lock_guard、unique_lock对比
a. lock_guard只有一个构造函数和析构函数,不能复制,不能赋值,没有提供其他接口。仅为mutex在一个作用域中的加锁和解锁提供了方便。
b. unique_lock提供了更多的接口。它最简单的用法和lock_guard一样。它可以复制、赋值,交换(swap),而且像是mutex的代理(proxy)。
c. 二者都不会控制mutex的生命周期,所以需要保证mutex的生命周期覆盖二者的生命周期。
4. <thread>库
1)thread
创建一个线程。
a. join
等待线程结束。会阻塞调用此函数的线程。
2)this_thread
代表当前线程。
#include <thread>
#include <iostream>
void ThreadRoutine(){
int count = 1000000;
float base = 1000;
float factor = 0.99F;
// 执行100万次浮点数运算
for(int i = 0; i < count; i++){
base *= factor;
}
std::cout << "thread " << std::this_thread::get_id() << std::endl; // 打印当前线程的ID
}
int main(int argc, _TCHAR* argv[]){
std::thread thread0(ThreadRoutine, 0);
thread0.join();
std::thread thread1(ThreadRoutine, 1);
thread1.join();
std::thread thread2(ThreadRoutine, 2);
thread2.join();
std::cout << "thread main" << std::endl; // 等待所有线程结束
return 0;
}
5. <utility>库
1)move
template <class T>
typename remove_reference<T>::type&& move (T&& arg) noexcept;
a. 右值(rvalue)
临时存储的表达式结果,如常量,函数返回值,构造函数调用。
b. 左值(lvalue)
一个相对持久的内存地址。可以用来存储右值。
class A{
public:
A(){}
};
int FnReturnValue(){
// 这里的lvalue也是个左值!函数的返回结果是个右值
int lvalue = 1;
return lvalue;
}
int main(){
// 函数调用产生一个右值,存储在栈上,如果没有左值接收,调用结束后在清理栈的时候会清除掉
FnReturnValue();
// lvalue是个左值,用来接收函数调用返回的右值
int lvalue = FnReturnValue();
// 产生右值,是A的对象,没有左值接收,立即析构
A();
// 产生右值,字符串字面值,没有左值接收,丢弃
"hello, world!";
return 0;
}
返回参数arg的右值引用(rvalue reference)。move强制转移值的语义(move semantics),即使值是个左值。示例:
#include <utility>
#include <vector>
#include <algorithm>
#include <iostream>
class A{
public:
A() : id(base++){
std::cout << "A(): " << id << std::endl;
}
A(const A& right) : id(base++){
std::cout << "A(const A&): " << id << " from " << right.id << std::endl;
}
// move constructor
// 如果有此定义,move会调用它,否则会调用copy constructor
A(A&& right) : id(base++){
std::cout << "A(A&&): " << id << " from " << right.id << std::endl;
}
~A(){
std::cout << "~A(): " << id << std::endl;
}
private:
int id;
static int base;
};
int A::base = 0;
int main(int argc, _TCHAR* argv[]){
typedef std::vector<A> VectA;
VectA objs;
std::cout << "push a0" << std::endl;
A a0;
objs.push_back(a0); // 复制一次
std::cout << "push a1" << std::endl;
A a1;
objs.push_back(std::move(a1)); // 移动或复制
std::cout << "push a2" << std::endl;
objs.push_back(A()); // 复制一次
std::cout << "after this" << std::endl;
return 0;
}
6. <memory>库
1)unique_ptr、shared_ptr
unique_ptr不能存入容器中,因为它不能拷贝、赋值。shared_ptr能。