C++记录 第五章
1、资源是指程序中符合先获取后释放(显式或隐式)规律的对象,比如内存、锁、套接字、线程句柄和文件句柄等。
2、unique_ptr对应所有权唯一情况;shared_ptr对应所有权共享的情况;智能指针是防止由于编程疏忽造成的内存泄露。
3、通过unique_ptr可以把自由存储上申请的对象传递给函数或从函数中传出来。
4、unique_ptr是独立对象或数据的句柄,以RAII的机制控制其他对象的生命周期,并且都通过移动操作使得return语句简单高效。
5、shared_ptr的对象使用拷贝操作而非移动。某个对象的多个shared_ptr共享该对象的所有权,只有当最后一个shared_ptr被销毁从被销毁。
6、除非确实需要共享所有权,否则不轻易使用shared_ptr。shared_ptr没有制定任何规则用以指明共享指针的哪个拥有者有权读写对象。虽解决资源管理问题,但数据竞争和其他形式的数据混淆依旧存在。
7、当我们需要使用指针的语义时,应选择智能指针(unique_ptr)而非特定操作的资源句柄(vector和thread)。
- 共享某对象,需要如多个指针或引用指向被共享的对象,使用shared_ptr(所有人都知道资源用且只有一个拥有者)
- 指向一个多态对象时,很难确切制定对象的类型,甚至其大小。应该使用指针或引用,unique_ptr成为必然选择。
- 共享的多态对象会使用shared_ptr。
当需要从函数返回对象的集合时,不必使用指针,而是容器能让该任务简单高效。
8、并发,多任务同时运行,用以提高吞吐率(多个处理器共同完成单个运算)和提高响应速度(允许程序的一部分在等待响应,另一部分继续执行)。
9、标准库支持单一地址空间并发执行多个线程。
10、可以与其他计算并行执行的计算称为任务。线程是任务在程序中的系统级表示。若要启动一个与其他任务并发执行的任务,可以构造std::thread(在 <thread>
中)并将任务作为实参。这里任务是函数或函数对象的形式出现。
void f();//函数
struct F{// 函数对象
void operator()();//F调用运算符
}
void user()
{
thread t1 {f};// f()在独立线程中执行
thread t2 {F()};//F()()在独立的线程中执行
t1.join();//等待t1完成
t2.join();//等待
}
join()保证我们在线程完成后从退出user(),其中"join"的意思是"等待线程结束"
11、一个程序的所有线程共享单一地址空间,而进程间通常不直接共享数据。优于共享单一地址空间,线程间可通过共享对象相互通信。通过锁或其他防止数据竞争(对变量不受控制的并发访问)的机制来控制线程间通信。
12、定义并发程序任务目标是保持任务的完全隔离,唯一例外是任务间通信部分,该通信应以简单而明显的方式进行。并发任务的最简单方式是把它看作一个可以与调用者并发执行的函数。为此传递实参获取结果并保证二者不会同时使用共享数据(不存在数据竞争)即可。
13、任务间需要共享数据,要确保同一时刻至多用一个任务可以访问给定对象使用 mutex
,thread使用lock()操作获取互斥对象。共享对象和mutex间是一种常规对应关系,只需要哪个mutex对应哪个数据即可。
14、推迟加锁解决同时获取多个锁造成死锁。
unique_lock<mutex> lck1{m1,defer_lock};// 推迟加锁,还未尝试获取mutex
unique_lock<mutex> lck2{m2,defer_lock};
unique_lock<mutex> lck3{m3,defer_lock};
// ...
lock(lck1,lck2,lck3);//获取全部三个锁
lock()调用只有在获取全部mutex实参从会继续执行,当其持有mutex绝不阻塞(“睡眠”),自然不会导致死锁。unique_lock的析构函数保证thread离开作用域,mutex会释放。
15、不要为了所谓“效率”不加思考、不经测试地使用共享数据进行线程间通信。
16、duration_case可将时间单位调整为期望的纳秒。<chrono>
头文件中。
17、外部事件实现线程间通信的是使用condition_variable,定义在<condition_variable>
头文件中。其提供一个机制,允许一个thread等待另一个thread,特别是允许一个thread等待某个条件(condition,通常称为一个事件,event)发生,这种条件通常是其他thread完成工作产生的结果。
18、标准库允许程序员在抽象任务层(工作并发执行)进行操作,而不是在底层的线程和锁的层次直接进行操作。<future>
头文件中。
- future和promise用来在一个独立线程时创建出任务并返回结果
- package_task是帮助启动任务以及连接返回结果
- async()以非常类似调用函数的方式启动一个任务
19、future和promise允许在两个人物间传输值,无需显式使用锁–“系统”高效地实现这种传输。思路:当一个任务需要向另一个任务传输某个值,它把值放入promise中。实现以自己方式令该值出现在对应future中,如何从中读值(通常是任务的启动者读取)。
promise提供future的get相匹配的简单“放置”操作(set_value()和set_exception())。
20、package_task简化任务连接future和promise,提供包装代码,负责把任务的返回值或异常放入一个promise中。调用get_future()向package_task发出请求,则返回对应promise的future。可以接受模板参数表示任务类型,而package_task斌被拷贝,使用move()操作是必须的。
21、async(),启动可异步执行的任务。将一个函数的“调用部分”和“获取结果部分”分离开来,并将这两个部分与任务的实际执行分离开来。async()使得不必操心线程和锁,只需考虑可能异步执行的任务。
限制:不要视图堆共享资源且需要用锁机制的任务使用async()。
async()会根据锁了解的调用发生时系统可用资源量确定使用多少个thread。
21、广泛工具
- clock和duration【时间段】,用于度量时间
- iterator_traits和is_arithmetic等类型函数,用于获取类型信息
- pair和tuple用于表示小规模且由异构数据组成的集合。
22、类型函数是指在编译时求值的函数,它接受一个类型作为实参或者返回一个类型作为结果。
<limits>
的numberic_limits,给数字类型提供有用信息。最小浮点数numberic_limits<float>::min()
- (模板)元编程,允许程序进行更严格的类型检查以获得更优的性能。
23、iterator_traits检查当前容器支持哪种迭代器【随机访问迭代器还是前向迭代器】。<iterator>
头文件
24、decltype()是内置函数,返回其实参已声明类型。
25、Iterator_type<C>
返回C的迭代器类型(即C::iterator),而Iterator_category<Iter>()
构建一个”标签“值以指示提供的是哪种迭代器:
- 如果C的迭代器支持随机访问,则取值为std::random_access_iterator_tag
- 如果支持前向访问,则为std:forward_iterator_tag
通过标签值以编译时确定从两种排序算法选取一种使用的技术称为标签分发。
26、类型谓词是简单类型函数,负责回答关于类型的问题。<type_traits>
头文件
bool b1 = Is_arithmetic<int>();//Yes,int是一种算术类型
bool b2 = Is_arithmetic<string>();//No,string不是一种算术类型
典型谓词以:is_class,is_pod,is_Iiteral_type,has_virtual_destructor和is_base_of
27、标准库pair定义在 <utility>
中被实现标准库组件。pair提供一些运算符,比如=,==,<。前提是其元素需支持。可用make_pair()快捷创建一个pair,而无须指定其类型。
auto pp = make_pair(v.begin(),2);//pp类型是pair<vector<string>::iterator,int>
如果用到元素个数不止两个或不足两个,应使用tuple,表示任意形式的元素序列。可用make_tuple()快捷创建一个tuple。每个元素对应一个编号,从下表0开始排列。只能提过 get<index>(tupleVariable)
的形式获取。
28、正则表达式,<regex>
头文件中,提供简单精炼描述文本中的模式,提供在文本中高效查找模式的方法。 regex_search(line,matches,pat)
负责从line中查找所有符合模式pat的子串。找到则存入matches中,不然其返回值为false。match类型为smatch,字符 's’表示“子(sub)”或“字符串(string)”,即是包含string类型匹配子串的vector。matches[0]是匹配得到的结果。
29、随机数生成器分成两部分:
- 一个引擎(engine),负责生成一组随机值或者伪随机值
- 一种分布(distribution),负责把引擎生成的值映射到某个数学分布时。
- 常见分布:uniform_int_distribution(生成所有整数概率相等),normol_distribution(正态分布)和exponential_distribution(指数增长)
30、标准库中类似于vector模板valarray,提供向量算术,在 <valarray>
中