不要试图编写独立于容器类型的代码
很多容器有类似的成员函数,同时迭代器几乎是一种泛化的操作,某一天突然意识到之前的容器不是最佳选择,你想使用另一种容器类型,便于转化,使用封装技术,最简单的方式是通过对容器类型和其迭代器类型定义typedef,这样做同时可以节省一些编码工作。现在可以使用auto。
确保容器中的对象拷贝正确而高效
容器中保存对象,但并不是你提供的容器的那些对象,以往存入和取出一个对象都会发生对象的拷贝,当对连续内存容器插入和删除时,现有元素的位置也经常会被移动,这也是拷贝的过程。拷贝耗时。
对象中有指针则需要注意是否需要深拷贝?
容器中存的是基类类型对象,存入其子类对象几乎总是错误的。会导致“剥离”。
为了高效、正确,并防止“剥离”问题的一个简单的办法是是容器包含指针而不是对象。
调用empty而不是检查size()是否为0
对任一容器C,下面的代码
if(0 == c.size())
if(c.empty())
是等价的,但使用empty()。因为empty()通常被实现为inline函数,同时empty对所有的标准容器都是常数时间。
如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉
上面第2点建议容器中存放指针而不是对象,这就带来了这个问题,从这样的容器中删除某个元素时,这个元素指针所分配的堆内存并不会释放,需要我们自己去释放。
此段代码会有内存泄漏,我们需要在作用域结束前释放内存。那怎么解决这个问题呢?有以下几种方式:
1、自己写个循环释放:
2、更建议使用算法提供的循环 std::for_each, 当然这里需要提供释放函数,有函数指针、函数对象、lumbda三种方式,优先考虑函数对象和lumbda。
3、更好的办法是使用智能指针 可以选择std::shared_ptr 和 boost::shared_ptr。
线程安全问题
一般说来,stl对于多线程的支持仅限于下列两点:
1、多个读取者是安全的。 即多个线程可以同时读取一个容器中的内容。 即此时多个线程调用容器的不涉及到写的接口都可以 eg find, begin, end 等.
2、对不同容器的多个写入者是安全的。即多个线程对不同容器的同时写入合法。
为了效率,没有给所有操作加锁。不同线程同时读同一容器对象没关系,不同线程同时写不同的容器对象没关系。但不能同时又读又写同一容器对象的。因此,多线程要同时读写时,还是要自己加锁。
能同时在同一容器上由不同线程调用const成员函数。而且,成员函数begin()、end(),rbegin()、rend()、front()、back()、data()、find()、lower_bound()、upper_bound()、equal_range()、at()和除了关联容器中的operator[]对于线程安全的目标表现如同const(即它们亦能同时在同一容器上由不同线程调用)。更广泛而言,C++标准库函数不修改对象,除非这些对象能直接或间接地经由函数参数,包含this指针访问。
同一容器中不同元素能由不同线程同时修改,除了std::vector<bool>的元素。
迭代器操作(例如自增迭代器)读但不修改底层容器,而且能与同一容器上的其他迭代器操作同时由const成员函数执行。非法化任何迭代器的容器操作修改容器,且不能与任何在既存迭代器上的操作同时执行,即使这些迭代器未被非法化。
其他不安全的情况需要加锁,注意锁的粒度。