1. auto_ptrs
1)auto_ptrs cannot share ownership
2)auto_ptrs are not provided for arrays(auto_ptr 使用operator delete 语义,尽量使用vector 代替数组)
3)auto_ptrs don't meet the requirements for container elements
const auto_ptr可以使拷贝auto_ptr 的操作非法。
const auto_ptr<T> pt1(new T);
auto_ptr<T> pt2(pt1); //error;
auto_ptr<T> pt3;
pt3 = pt1; //error;
如果使用auto_ptr, 你的类就必须提供自己的具有正确语义的析构函数,拷贝构造函数和拷贝赋值函数, 或者禁止掉拷贝构造函数和拷贝赋值函数.
2. Iterator Categories
1)Input iterator
2)Output iterator
3)Forward iterator
4)Bidirectional iterator
5)Random access iterator
Iterator Adapters
1)Reverse Iterators
rbegin() is container::reverse_iterator(end())
rend() is container::reverse_iterator(begin())
2)Insert Iterators
3)Stream Iterators
3. std::cin 和 std::cout
std::basic_istream<char, std::char_traits<char> >
std::basic_ostream<char, std::char_traits<char> >
4. std::remove 和 erase
remove 只是简单地用未删除对象来填补被删除对象留下的缺口,每个被删除对象在尾部都会留下一个相应的dead对象, 最后remove 返回一个迭代器,指向第一个dead对象, 如果没有对象被删除,remove 将返回end迭代器。
remove接收指定它操作的元素区间的一对迭代器。它不接收一个容器,所以remove不知道它作用于哪个容器。此外,remove也不可能发现容器,因为没有办法从一个迭代器获取对应于它的容器。remove并不“真的”删除东西,因为它做不到。另外有两种“类似remove”的算法:remove_if和unique
5. 为了让状态性predicate 正常工作, 对算法有哪些必要的要求
1)算法绝对不能对predicate 做复制, 自始至终只能使用同一个对象
2)算法必须以某个已知的顺序将predicate作用到区间的元素上,通常是从第一个到最后一个
6. typename
对有依赖性的名称使用typename
7. 获取指向容器内部的指针或引用
vector<char> v;
char* p = &v[0];
C++标准保证, 如果一个符合标准的序列容器提供operator[],这个运算符必然返回类型T的左值, 而左值是可以取得地址的。
C++标准库要求vector 必须对bool进行特化, 于是作为一个特化模板,vector<bool>不是一个容器,它不符合标准库容器的条件。 实际上,vector<bool>并没有存储bool. &v[x]也取不到元素的地址。
8. vector 和 deque
vector 和deque 在结构上的主要区别在于, 这两种容器的内存组织方式不一样, deque 是按页,page 或 块 chunk来分配内存的, 每个page包含固定数目的元素, 他在序列的两端插入元素都很有效率。 相反,vector 分配一块连续的内存,只是在序列的尾端插入元素的时候才有效率。
1)即使在容器的前端,deque也提供了常数时间的insert 和 erase, 而vector 不行。
2)deque使用内存的方式对操作系统更友好。
3)在体积增长方面, 他比vector 更有效率,vector 提供的两个函数,capacity()和reserve(), deque并不需要它们。
4)用vector 替换C style的数组在使用中是安全的, 而且你应该尽量使用vector 或者deque,而不使用数组。
9. vector
vector<int> v;
v[0];//不做范围检查, 如果不在有效范围, 行为未定义
v.at(0)//如果不在有效范围, throw std::out_of_range
resize / size:size 指目前容器有多少个元素, resize 则会在容器尾部添加或删除一些元素,用来调整容器的大小。
reserve / capacity:capacity告诉你最少添加多少个元素才会导致容器重分配内存,而reserve在必要的时候总是会使容器的内部缓冲区扩充至更大的容量,以确保至少能满足你所指出的空间大小
10. 尽量使用!=而不是<来比较两个迭代器
只有随机访问迭代器支持<
11. const_iterator
如果不需要对容器的元素作任何改动的时候,最好使用const_iterator
12. 指向数组内元素的指针永远都是迭代器, 迭代器并非总是指针
将迭代器转型为指针 &*iter, 先将迭代器解引用,获得容器内对象的直接引用,然后获取它的地址。
13. 函数模板的link种类
避免使用export
1)包含模式
2)分离模式
14. empty() 与 size()==0
用empty来代替检查size()是否为0
15. STL容器的线程安全性
多个读取者是安全的。多线程可能同时读取一个容器的内容,这将正确地执行。当然,在读取时不能有任何写入者操作这个容器。
对不同容器的多个写入者是安全的。多线程可以同时写不同的容器。
16. 使用“交换技巧”来修整过剩容量
vector<Contestant> v;
string s;
... // 使用v和s
vector<Contestant>().swap(v); // 清除v而且最小化它的容量
string().swap(s); // 清除s而且最小化它的容量
17. 关联容器的operator<
永远让比较函数对相等的值返回false
18. 判断类型是否为class
// traits/isclasst.hpp
template<typename T>
class IsClassT {
private:
typedef char One;
typedef struct { char a[2]; } Two;
template<typename C> static One test(int C::*);
template<typename C> static Two test(…);
public:
enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
enum { No = !Yes };
};
19.for_each 和 transform
for_each 可以改变操作的参数, 因此该参数必须以pass by reference 方式传递
transform 可以将操作的返回值赋给元素
20. 排序算法
sort 内部采用quick sort
partial sort 内部采用 heap sort
stable sort 内部采用 merge sort
21. for_each
template <class InputIterator, class Function>
Function for_each (InputIterator first, InputIterator last, Function f);
对区间[first, last)的每一个元素调用f(elem), 并返回 f 的一个副本
* f 的任何返回值都会被忽略掉