《Effective C++》
条款11 在operator=中处理“自我赋值”
自我赋值
证同测试:
if(this==&rhs)return*this;
影响并行处理效率
记住副本:
type* memberO=member;
pmember=new type(*rhs.member);
delete memberO;
return *this;
copy and swap:
class_type temp(rhs);
swap(rhs);
return *this;
条款30看不明白
条款39:明智而审慎地使用private继承
private继承只是一种代码实现方式而没有任何的意味
如果需要一个不含virtual函数和non-static成员变量的空基类,则可以使用private继承,表示EBO(empty base optimization,空白基类最优化)
条款40:明智而审慎地使用多重继承
钻石继承可以用virtual public解决
virtual bases的继承体积会变大,速度会变慢,所以尽量不要用,如果要用,尽可能避免在其中放置数据,类似于Java的接口
条款41:了解隐式接口和编译器多态
- 对classes而言接口是显式的,以函数签名为中心,多态则是通过virtual函数发生于运行期。
- 理解为classes定义完函数后,运行时通过virtual函数调用不同子类的函数。
- 对template参数而言,接口是隐式的,奠基于有效表达式。多态则是通过template具现化和函数重载解析(function overloading resolution)发生于编译期。
- 理解为template定义完函数后,只有拥有函数内调用的成员函数的类才能使用template函数,而在编译期内,就需要告知template使用的什么类。
《STL源码剖析》
特化:开一个特殊的模版类
const解引用获得右值
vector
第一个元素获得1,否则扩容成两倍,搬移
deque
为多个缓冲区,sort时先搬到一个vector然后排序完搬回,使用一个索引表保存缓冲区
stack
template<class T,class Sequence=deque<T> >
默认底层实现为deque,可以传参实现其他构造
stack不提供迭代器
queue
同stack
heap
使用vector实现的堆,也可以使用array
priority_queue
底部是max-heap
slist
单向链表
set
底层红黑树,使用insert_unique()
map
底层红黑树,使用pair,按键值排序
multiset
和set基本相同,使用insert_equal()
multimap
和map基本相同,使用insert_equal()
《Effective Modern C++》
条款1:理解模版型别推导
数组退化成指针时,如果使用引用传递实参,则可以获得数组型别:
template<typename T>
void f(T ¶m);
const char name[] = "J. p. Briggs";
f(name);
T的型别推导结果是const char [13],f的形参型别被推导为const char (&)[13]。
可以创造出一个模板推导数组含有的元素个数:
template<typename T, std::size_t N>
constexpr std::size_t arraySize(T (&)[N]) noexcept {
return N;
}
int keyVals[] = {1, 3, 7, 9, 11, 22, 35};
int mappedVals[arraySize(keyVals)];
条款2 理解auto型别推导
- 在一般情况下,auto型别推导和模版型别推导是一模一样的,但是auto型别推导会假定用大括号括起的初始化表达式例如
auto x{27}
代表一个std::initializer_list
,但模版类型推导却不会 - 在函数返回值或lambda式的形参中使用auto,意思是使用模版类型推导而非auto型别推导