Effective STL读书笔记

【绝版C++书籍】《Effective STL读书笔记 Effective STL读书笔记写在前面《Effective STL》中可能过的内容1 容器第1条:慎重选择容器类型。第2条:不要试图编写独立于容器类型的代码。第3条:确保容器中的对象拷贝正确而高效。第4条:调用empty而不是检查size()是否为0。第5条:区间成员函数优先于与之对应的单元素成员函数。第6条:当心C++编译器最烦人的分析机制。第7条:如果入容器中包含了通过new操作创建的指针,切记在容器对象析构前将delete掉。第8条:切勿创建包含auto_ptr的容器对象。第9条:慎重选择删 阅读详情
1、慎重选择容器类型
    a.标准STL序列容器:vector、string、deque、list
    b.标准STL关联容器:set、 multiset、 map、 multimap
    c.非标准序列容器:slist、 rope
    d.非标准关联容器:hash_set、 hash_multiset、 hash_map、 hash_multimap
    e.vector<char> 作为string的替代
    f.vector作为标准关联式容器的替代。
    g.几种标准的非STL容器:数组、bitset、valarray、 stack、 queue、 priority_queue。

    vector、list和 deque的选择:vector是默认应使用的序列类型;当需要频繁在序列的中间做插入和删除操作时,应使用list; 当大多数插入和删除操作发生在序列的头部和尾部时,deque是应考虑的数据结构。
2、不要试图编写独立于容器类型的代码
    因为每个容器都有自己独特的使用方式。可以将这些容器封装在类里使用,减少外界对容器特性的依赖。
3、确保容器中的对象副本正确而高效
    容器保存的对象是你提供给容器的对象的副本,当从容器中取出一个对象时,得到的也是该对象的副本。进去的是副本,出来的也是副本。
    当对象的复制操作非常复杂时,导致程序的性能的下降,而且如果容器中存放的是基类对象,当将派生类对象复制给基类对象时,发生剥离。 使复制动作高效、正确,并防止剥离问题发生的一个简单办法是使容器包含指针而不是对象。
   
4、调用empty()而不是检查size()是否为0
    empty通常被实现为内联函数,并且它所做的仅仅是返回size是否为0。empty对所有的标准容器都是常数时间,而对于一些list实现,size花费线性时间。
5、区间成员函数优先于与之对应的单元素成员函数
    区间成员函数使用两个迭代器参数来确定该成员操作所执行的区间。
    区间成员函数写起来更容易,更能清楚地表达你的意图,而且它们表现出了更高的效率。
6、当心C++编译器最烦人的分析机制
    class Widget{...};  Widget w();得到的不是Widget类型的对象,而是声明了一个函数w,返回值是WIdget类型的。STL也有类似的误用。
7、如果容器中包含了通过new操作创建的指针,切记在容器对象析构钱将指针delete掉。
    使用引用计数形式的智能指针shared_ptr是一个很好的选择,它能保证释放分配的内存,即便是发生了异常。
8、切勿创建包含auto_ptr的容器对象。
    auto_ptr的容器是被禁止的。因为当复制一个auto_ptr时,它所指向的对象的所有权被移交到考入的auto_ptr上,而它自身被设置为NULL。
9、慎重选择删除元素的方法。
10、了解分配子(allocator)的约定和限制
11、理解自定义分配子的合理用法
12、切勿对STL容器的线程安全性有不切实际的依赖
    对容器成员函数的每次调用,都锁住容器直到调用结束;
    在容器所返回的每个迭代器的生存期结束前,都锁住容器;
    对于作用于容器的每个算法,都锁住该容器,直到算法结束。
    最好把互斥器封装起来Lock的构造函数加锁,析构函数解锁,这样在发生异常时保证可以解锁。

第二章  vector和string
 
13、vector 和 string 优先于动态分配的数组。
    如果使用new来动态分配内存,你要承担的责任:
    必须确保以后会有人用delete来删除所分配的内存;
    必须确保使用了正确的delete形式;
    必须确保只delete了一次。
14、使用reserve来避免不必要的重新分配
    reserve(Container::size_type n)强迫容器把它的容量变为至少是n,前提是n不小于当前的大小。
    当一个元素需要被插入而容器的容量不够时,就会发生重新分配过程(包括原始内存的分配和释放,对象的复制和析构,迭代器、指针、引用的失效)。 避免重新分配的关键在于,尽早使用reserve,把容器的容量设为足够大。
15、注意string实现的多样性
16、了解如何把vector 和 string 数据传给旧的API
    vector v; 得到一个指向v中数据的指针,应用的形式是 &v[0];
    string s;对应的形式是 s.c_str();
17、使用swap技巧出去多余的容量
    vector<int> v;  .....;  v<int>().swap(v);
    string s; .....; string().swap(s);
18、避免使用vector<bool>
    vector<bool>不是STL容器。每个bool仅占一个二进制位,有一个6位的字节容纳8个bool。
    可以用deque<bool>替代,也可以用bitset替代。

第三章 关联容器
19、理解相等和等价的区别
    相等是以operator==为基础的。
    等价是以operator<为基础的。对于两个对象x,y,如果按照关联容器c的排列顺序,每一个都不在另一个的前面,即 x < y 为假, y < x 为假,那么称这两个对象按照c的排列顺序有等价的值。
20、为包含指针的关联容器指定比较类型
    默认情况下关联容器的比较函数对象对指针的操作是指针值的比较,而不是指针所指对象的比较,因为容器中存储的就是指针的值。因此一般要编写自己的比较函数对象,自定义比较方法。
struct DereferenceLess
{
    template<typename PtrType>
    bool operator() (PtrType pT1, PtrType pT2) const
    {
        return *pT1 < *pT2;
    }
};

21、总是让比较函数在等值情况下返回false
22、切记直接修改set或multiset中的键
    修改键值将会打破容器的有序性。
23、考虑用排序的vector替代关联容器
    标准关联容器使用的是红黑树作为底部结构实现的。这就对每个元素对象带来了额外的开销:指向左孩子的指针、指向右孩子的指针,一般还有指向父节点的指针。当数据量大时,会导致容器分配更多的页,在使用时要不断的发生页错误而导致页的换入换出,使得系统显著变慢。
    而对于排序的vector容器,每个元素对象没有额外开销,末尾多余的空闲空间也可以去掉。这样比关联容器在存储相同数量的元素时,分配的页就较少,发生页错误的概率也就减少。
    但是必须保证vector是排序的,而且一般只用于查找操作,而用于插入和删除将导致效率的下降。
24、当效率至关重要时,请在map::operator[] 与 map::insert之间慎重做出选择
    如果要更新一个已有的映射表元素,则应优先选择operator[]; 但是如果要添加一个新元素,那么最好是选择insert,因为operator[]要首先创建一个默认的对象,然后给该对象进行赋值操作,这就导致了三个函数的调用:默认构造函数、析构函数、赋值操作函数。
25、熟悉非标准的散列容器。
    hash_set、 hash_multiset、 hash_map、 hash_multimap
    元素是未排序的,查找时间为O(1)

第4章 迭代器
26、iterator优先于const_iterator、 reverse_iterator以及const_reverse_iterator
    减少混用不同类型的迭代器,尽量使用iterator 替代 const_iterator
27、使用distance 和 advance 将容器的const_iterator 转换成 iterator
    iterator 和 const_iterator  之间不存在类型转换,隐式和显示都不行。
    deque<int> d;
    deque<int>::iterator iter;
    deque<int>::const_iterator citer;
   .....
    iter = d.begin();
    advance(iter, distance< deque<int>::const_iterator >(iter, citer));
28、正确理解由reverse_iterator 的 base()成员函数所产生的iterator用法。
29、对于逐个字符的输入请考虑使用istreambuf_iterator。

第5章 算法
30、确保目标区间足够大
    要在算法执行过程中增大目标区间,请使用插入型迭代器,比如ostream_iterator,或者由back_inserter、 front_inserter、 inserter返回的迭代器。
31、了解与各种排序有关的选择
    sort、 partial_sort(部分排序)、 nth_element(类似于快速排序的寻找枢轴位置的函数)
    a.如果需要对vector、string、deque或者数组中的元素执行一次完全排序,那么可以使用sort或者stable_sort。
    b.如果有一个vector、string、deque或者数组,并且只需要对等价性最前面的n个元素进行排序,那么可以使用partial_sort
    c. 如果有一个vector、string、deque或者数组,并且需要找到第n个位置上的元素,或者,需要找到等价性最前面的n个元素但是又不必对这n个元素进行排序,那么nth_element正是所需要的函数。
    d.如果需要将一个标准序列容器中的元素按照是否满足某个特定的条件区分开来,那么partition和stable_partition是所需要的。
32、如果确实需要删除元素,则需要在remove这一类算法之后调用erase。
    从容器中删除元素的唯一方法是调用该容器的成员函数,而remove并不知道它操作的元素所在的容器,所以remove不可能从容器中删除元素。
 
33、对包含指针的容器使用remove这一类算法时要特别小心
    为了防止内存泄露,最好用智能指针
34、了解哪些算法要求使用排序的区间作为参数。
    binary_search、 lower_bound、 upper_bound  equal_range
    set_union   set_intersection    set_difference
    merge includes
35、通过mismatch或lexicographical_compare实现简单的忽略大小写的字符串比较。
36、理解copy_if算法的正确实现
37、使用accumulate 或者 for_each 进行区间统计

第6章 函数子、函数子类、函数及其他
38、遵循按值传递的原则来设计函数子类
    如果一个函数对象包含了较多的数据成员或者 含有虚函数,则将这些数据成员和虚函数封装到一个单独的类中,在函数对象中用一个指针指向这个单独类对象。
39、确保判别式是纯函数
40、若一个类是函数子,则应使它可配接
41、理解ptr_fun、mem_fun和mem_fun_ref的由来
42、确保less<T> 与 operator<具有相同的语义

第7章 在程序中使用STL
43、算法调用优先于手写的循环
    使用算法可以提高:效率、正确性、可维护性
44、容器的成员函数优先于同名的算法。
45、正确区分count、 find、 binary_search、 lower_bound、 upper_bound和equal_range
46、考虑使用函数对象而不是函数作为STL算法的参数
47、避免产生直写型(write-only)的代码
48、总是包含正确的头文件
    <vector> 包含了 <string>
    <algorithm> 包含了 <string>
    <iostream> 包含了 <string> 和 <vector>
    <string> 包含了 <algorithm>
    <set>  包含了 <functional>
    标准的函数子(比如less<T>)和函数配接器被声明在头文件<functional>中。
49、学会分析与STL相关的编译器诊断信息。
50、熟悉与STL相关的Web站点。
    SGI STL 站点:http://www.sgi.com/tech/stl/
    STLport 站点:
    Boost Web 站点
Effective STL_读书笔记 1. 容器。 阅读详情

相关推荐

哈希算法--暴雪的mpq技术

摘自论坛:http://bbs.csdn.net/topics/300172062,先保存下来   强烈的推荐你使用暴雪的mpq技术 我在个人机器上实现过4000万条字符串存储,碰撞很小 需要代码的话,请留下你的邮箱 这里留下我以前用过的一个小程序,稍做修给后应该可以满足你的要求: #include using namespace std; #define nTableSize

大冰的小屋 3201

Effective STL读书笔记

Effective STL 剥离 向基类对象的容器中插入派生类对象,派生类对象独有的特性会丢失 empty 检查容器是否为空用empty而不是size 善于使用区间成员函数(assign,etc) v1.assign(v2.begin() + v2.size()/2, v2.end()) 16.将vectorstring传给旧的API(c api) vector元素是连续存储在内存中的 if (...

huatian5的博客 340

别再死记硬背了!用TwinCAT 3手把手教你配置EtherCAT伺服驱动的PDO映射(DS402协议)

本文详细介绍了如何使用TwinCAT 3配置EtherCAT伺服驱动的PDO映射(DS402协议),涵盖环境准备、设备扫描、PDO映射实战及高级技巧。通过具体操作步骤常见问题排查,帮助工程师快速掌握EtherCAT通信配置,提升运动控制系统的效率稳定性。

weixin_29185493的博客 287

Effective STL 读书笔记

effective c++读书笔记

haotiangg的专栏 1807

Effective stl读书笔记

关联容器 条款24 当关乎效率应该在map::operator[]map-insert之间仔细选择 新增元素 class Widget { public: Widget() { std::cout << "Widget::Widget()" << std::endl; } Widget(double val) { _val = val; std::cout << "Widget::Widget(double)"

qq_43003442的博客 262

Effective STL 精华版读书笔记

文章目录容器vectorstring1.仔细选择你的容器2.关联容器且带起算法仿函数、仿函数类、函数等使用STL编程 容器 vectorstring 1.仔细选择你的容器 2. 关联容器 且带起 算法 仿函数、仿函数类、函数等 使用STL编程 ...

小鱼酱的博客 669

读书笔记-effective STL

目录: 1.vector,string 2迭代器 3.关联容器 4.容器自己补充的关于stl的一点内容 5.stl中的排序 6.删除stl容器元素的方法1.vector,string vectorstring优先于使用数组原因:vectorstring是功能齐全的stl容器,支持的功能也比较齐全。 使用reserve来避免不必要的重新分配 原因:容器一般含有多余的空间,即siz

随心的专栏 641

读书笔记】【Effective STL】容器

读书笔记】【Effective STL】容器。

做一些记录工作。 632

effective stl 读书笔记

本文在赖勇浩的笔记上继续写的^_^ 第1条:慎重选择容器类型; 第2条:不要试图编写独立于容器类型的代码。 第3条:确保容器中的对象拷贝正确而高效; 第4条:调用 empty 而不是检查 size() 是否为 0。第5条:区间成员函数优先于与之对应的单元素成员函数。 区间成员函数写起来更容易,更能清楚地表达你的意图,而且它们表现出了更高的效率。 几乎所有目标区间被插入迭...

395

effective STL读书笔记

转载地址:http://www.cnblogs.com/luxiaoxun/archive/2012/12/05/2803136.html #.string 建议   使用string 的方便性就不用再说了,这里要重点强调的是string的安全性。       string并不是万能的,如果你在一个大工程中需要频繁处理字符串,而且有可能是多线程,那么你一定要慎重(当然,在多线程下你使

wangwenwen的专栏 722

47. 避免产生"直写型"(write-only)的代码

什么叫直写型代码? 编写代码的候,它看似非常直接简洁,因为他是由某些基本想法自然而形成的。然后,阅读代码的人却很难将最终的语句还原成它所依据的思路。虽然很容器一编写,但是难以阅读理解。 比如下面代码: std::vector<int> datas; int x, y; ... datas.erase( std::remove_if(std::find_if(datas.rbeg...

xupeng1644的博客 6408

Effective STL读书笔记

链接:https://pan.baidu.com/s/1XuUqVs4irA1VQIRxGXUqlA 密码:0m0e

inception_wzd的博客 288

47 避免产生“直写型”(write-only)的代码

假定有一个vector&lt;int&gt;,现在想删除其中所有的其值小于x,的元素,但是,最后一个其值不小于y的元素之前的所有元素应该保留下来: vector&lt;int&gt; v = {1,2,3,4,5,5,6,6,6,7,7,7,8,8,8}; v.erase( remove_if(find_if(v.rbegin(),v.rend(), bind2nd(grea...

hallå的博客 847

什么候可以不用实例化对象就可以调用类中成员函数

对于一个类A,表达式

大冰的小屋 1万+

WebSocket的简单使用

WebSocket一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket 使得客户端服务器之间的数据交换变得更加简单,允许服务端直接向客户端推送数据而不需要客户端进行请求,在 WebSocket API 中,浏览器服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并允许数据进行双向传送。——- 《维基百科》最近在项目中使用了WebSocket,开发了一个非常简单的服务器端

大冰的小屋 7878

对于内存越界访问的笔记

对于内存访问越界的操作在编译期编译器是不会报错的,而在

大冰的小屋 3185

C++中函数占位符在函数重载中的作用

今天看STL源码剖析,对于迭代器不同类型的重载函数的调用用到了函数占位符,之前没注意过,特记录下来。 代码只是简单的测试,没有特别意义: #include using namespace std; int __Sum( int a, int b, int ) { cout<<"__Sum( int a, int b, int )"<<endl; return a + b; } in

大冰的小屋 2283

【Bug已解决】Request timed out / API Timeout — Claude Code 请求超解决方案

方案适用场景推荐指数难度方案一:增加超大任务处理⭐⭐⭐⭐⭐低方案二:切换 SonnetOpus 太慢⭐⭐⭐⭐⭐低方案三:缩小范围大代码库⭐⭐⭐⭐⭐低方案四:优化网络网络延迟高⭐⭐⭐⭐中方案五:减少 MCPMCP 超⭐⭐⭐中方案六:流式响应长生成任务⭐⭐⭐低根本原因:请求超最常见原因是请求体过大(35%) Opus 模型推理慢(25%),默认 60 秒超阈值对大型任务不够最佳实践。

一键难忘的博客 5034

AutoCAD_C#Net面域布尔运算的应用.rar

AutoCAD制图中,面域(Region)是一个很重要的内容,应用于土地调查工程测量,利用实体编辑的交、并、差等运算方法可以准确快速地解决地块的分切,拓扑问题,在CAD中实现GIS的部份功能。本文向大家介绍利用C#.Net2016二次开发,在AutoCAD中,实现面域布尔运算的批处理功能。开发项目中涉及的内容有:批量线对象生成面域、面域布尔运算、获取面域的环,圆弧曲线的等分、搜索线段集合组成多段线等。

上一篇: 在C++中模拟Java中final对虚函数的使用
下一篇: 高性能网络编程(一)----accept建立连接
大冰的小屋
博客等级 码龄13年 109粉丝 190原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值