1、由于继承的存在,拷贝会导致分割。那就是说,如果你以基类对象建立一个容器,而你试图插入派生类对象,那么当对象(通过基类的拷贝构造函数)拷入容器的时候对象的派生部分会被删除。
分割问题暗示了把一个派生类对象插入基类对象的容器几乎总是错的。如果你希望结果对象表现为派生类对
象,比如,调用派生类的虚函数等,总是错的。
一个使拷贝更高效、正确而且对分割问题免疫的简单的方式是建立指针的容器而不是对象的容器。也就是
说,不是建立一个Widget的容器,建立一个Widget*的容器。拷贝指针很快,它总是严密地做你希望的(指针
拷贝比特),而且当指针拷贝时没有分割。现智能指针的容器是一个吸引人的选择。
2、尽量使用区间成员函数代替它们的单元素兄弟(使用stl的copy、assign、insert等迭代器区间代替手写for循环逐个添加元素)。
●一般来说使用区间成员函数可以输入更少的代码。
● 区间成员函数会导致代码更清晰更直接了当。
●当处理标准序列容器时,应用单元素成员函数比完成同样目的的区间成员函数需要更多地内存分配,更频繁地拷贝对象,而且/或者造成多余操作。
3、set换成list的例子:
std::list<MDSWDMChannelID>& lst_channel_id; .......... itr_find = std::find(m_lst_channel_state.begin(), m_lst_channel_state.end(), *itr_channel);
原因:对list进行std::find查找,效率会非常差,方法会引入严重性能问题,请把m_lst_channel_state改为set。因为set底层是红黑树,具有自动排序的功能,查找会比较快。但是不适合频繁的插入和删除,因为这样需要重新构筑大堆序,比较耗时。
3、在声明一个vector的时候,尽量指明大小,如果输入数据不超过10^6,
那就声明一个10^6大小的vector,否则,vector的默认大小是10.(太小了),但是vector的大小可以自动扩大,不要以为仅仅是在已经分配的空间后面再多申请一块,而是新开辟一块空间,把原来的复制过去.想一下,如果你的vector不断的扩容,不断的复制,效率能不低吗?这就是有的网友问为什么STL的vector没有数组的效率高的原因.
虽然stl容器可以动态分配空间,尤其是顺序容器。但是很多情况下,为了避免对内存的多次分配,将会预先给容器分配很大的内存空间,等数据分配完成后,再进行去除多余的空间,这种方式可以有效提供程序的效率。
4: Set, Map, 都是基于RB-Tree的容器,所以有自动排序功能
插入删除,查找效率都很高,查找1000个记录,最多查找10次,查找1000000个记录,最多查找20次
注意事项: 许多人喜欢用,但是如果频繁的插入,删除,不建议使用.因为每插入一次或者删除一次,都要对RB-tree进行一次调整,n次插入,时间复杂度nlgn. 但是如果插入,删除不频繁的情况下是首选.
5: hash_set, hash_map, 都是基于hash_table的,没有自动排序功能
注意事项: 在声明的时候也要尽量指明大小,否则哈希表的容量达到thresh_hold的时候要自动扩容,所有元素再哈希一次.时间不容忽视. hash_table默认初始大小53, 然后扩容至97,193,389,故意是质数.默认的是朴素哈希函数:比如"apple"的hash code: 5*(55(5*‘a’+‘p’)+‘p’)+‘l’)+‘e’ % 53 = 78066%53 = 50
hash_map使用hash表来排列配对,hash表是使用关键字来计算表位置。当这个表的大小合适,并且计算算法合适的情况下,hash表的算法复杂度为O(1)的,但是这是理想的情况下的,如果hash表的关键字计算与表位置存在冲突,那么最坏的复杂度为O(n)。
RB-tree树查找,在总查找效率上比不上hash表,但是它很稳定,它的算法复杂度不会出现波动。在一次查找中,你可以断定它最坏的情况下其复杂度不会超过O(log2N)。而hash表就不一样,是O(1),还是O(N),或者在其之间,你并不能把握。
6、vector去除重复数据
vector<int>v; v.reserve(10000); for (int i = 1; i < 10; i++) v.push_back(i); vector<int>(v).swap(v);