《Effective STL》 读书笔记
Effective STL
剥离
向基类对象的容器中插入派生类对象,派生类对象独有的特性会丢失
empty
检查容器是否为空用empty而不是size
善于使用区间成员函数(assign,etc)
v1.assign(v2.begin() + v2.size()/2, v2.end())
16.将vector和string传给旧的API(c api)
vector元素是连续存储在内存中的
if (!v.empty()) {func(&v[0]);
}
不能用v.begin()
,因为这将返回一个迭代器,而不是指针
string元素不一定是连续存储在内存中的,所以有专门的成员函数
s.c_str()
17.使用swap将多余内存还给系统
`vector<int> contestents(10, 0);contestents.pop_back();cout << "Capacity is " << contestents.capacity() << "\n";// 10vector<int>(contestents).swap(contestents);cout << "Capacity is " << contestents.capacity() << "\n";// 9`
C++11起有了成员函数shrink_to_fit()
18.vector
失败的实验,可以采用deque
19.相等与等价
等价
!(a < b) && !(a > b)
20.为包含指针内容的关联容器指定比较类型
set里面存string*,但是想要set按照字符串的字典序排序。
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <set>using namespace std;struct StringPtrLess:public binary_function<const string*, const string*, bool> {//binary_function 于 C++11 弃用并于 C++17 移除。bool operator() (const string *ps1, const string *ps2) const {return *ps1 < *ps2;}};int main()
{set<string*, StringPtrLess> ss;string a = "sadad";string b = "dsfaf";ss.insert(&a);ss.insert(&b);for (auto it : ss) {cout << *it << "\n";}
}
模板类型:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <set>using namespace std;struct DereferenceLess {template<typename PtrType>bool operator() (PtrType pT1, PtrType pT2) const {return *pT1 < *pT2;}
};
int main()
{set<string*, DereferenceLess> ss;string a = "sadad";string b = "dsfaf";ss.insert(&a);ss.insert(&b);for (auto it : ss) {cout << *it << "\n";}
}
21.总是让比较函数在等值情况下返回false
如果set中的比较函数是operator<=,那么等价性的判断就 !(a <= b) && !(a >= b)
,显然为false,那么就认为 a 和 b 是不等价的。
那么set中就会包含两个相等的值,就破坏了 set 容器。
用于对关联容器排序的比较函数必须为他们所比较对象定义一个”严格的弱序化“
22.切勿直接修改 set 或 multiset中的键
map 和 multimap 中的键是 const 的
set 和 multiset中的键是非 const 的
试图修改 set 或 multiset 元素的代码将是不可移植的
应对方案:
- 不考虑移植性,非键部分可以改动
- 考虑移植性,修改非键部分可以采用强制类型转换(const_cast),来去掉访问的 const 性质
强制转换???有点奇妙
23.考虑排序vector代替关联容器
查找操作几乎不和插入、删除操作混在一起
24.效率至关重要,选择map::operator[]还是map::insert()
operator[] 先默认构造再赋值,所以单纯添加内容优先选择 insert()
26. iterator 优先于其他迭代器
27.const_iterator 转换成 iterator
#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
std::vector<int> v = {1, 3, 5};typedef std::vector<int>::iterator It;
typedef std::vector<int>::const_iterator CIt;int main()
{CIt ci = v.begin();It i = v.begin();std::advance(i, std::distance(i, ci));std::cout << *i << "\n";return 0;
}
上述代码无法通过编译,distance 的两个参数需是同一类型
解决方法是指明参数类型 std::advance(i, std::distance<CIt>(i, ci));
28.reverse_iterator 的 base() 成员函数产生的 iterator 用法
#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>int main()
{std::vector<int> v;for (int i = 0; i < 10; ++i) {v.push_back(i);}std::vector<int>::reverse_iterator ri = std::find(v.rbegin(), v.rend(), 7);std::vector<int>::iterator i(ri.base());std::cout << *ri << "\n";std::cout << *i << "\n";return 0;
}
base() 函数返回底层迭代器,指向 reverse_iterator 当前指向的下一个元素
http://upload.cppreference.com/mwiki/images/3/39/range-rbegin-rend.svg
如果在 ri 的前面插入一个元素,和在 ri.base() 前面插入一个元素的逻辑是一样的。
insert() 和 erase() 函数不接受 reverse_iterator 作为参数,需要使用 iterator。
#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>int main()
{std::vector<int> v;for (int i = 0; i < 10; ++i) {v.push_back(i);}std::vector<int>::reverse_iterator ri = std::find(v.rbegin(), v.rend(), 7);std::vector<int>::iterator i(ri.base());std::cout << *ri << "\n";std::cout << *i << "\n";v.erase(--i);for (int x : v) {std::cout << x << "\n";}return 0;
}
v.erase(–i);//应该是编译不过的,但是我编过了
但是中间解释不太懂
v.erase((++ri).base());//应该这样用
29.istreambuf_iterator
int main()
{ifstream input_file("int.txt");string file_data((istreambuf_iterator<char>(input_file)), istreambuf_iterator<char>());}
30.确保区间足够大
transform
transform(v.begin(), v.end(), res.end(), [](int x){return x;});//无效对象的赋值操作
生成迭代器
transform(v.begin(), v.end(), back_inserter(res), [](int x){return x;});
- back_inserter 返回的迭代器调用 push_back()
- front_inserter 返回的迭代器调用 push_front()
- inserter 把结果插入到特定位置
《Effective STL》 读书笔记相关推荐
- 读书笔记 | 墨菲定律
1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...
- 读书笔记 | 墨菲定律(一)
1. 有些事,你现在不做,永远也不会去做. 2. 能轻易实现的梦想都不叫梦想. 3.所有的事都会比你预计的时间长.(做事要有耐心,要经得起前期的枯燥.) 4. 当我们的才华还撑不起梦想时,更要耐下心来 ...
- 洛克菲勒的38封信pdf下载_《洛克菲勒写给孩子的38封信》读书笔记
<洛克菲勒写给孩子的38封信>读书笔记 洛克菲勒写给孩子的38封信 第1封信:起点不决定终点 人人生而平等,但这种平等是权利与法律意义上的平等,与经济和文化优势无关 第2封信:运气靠策划 ...
- 股神大家了解多少?深度剖析股神巴菲特
股神巴菲特是金融界里的传奇,大家是否都对股神巴菲特感兴趣呢?大家对股神了解多少?小编最近在QR社区发现了<阿尔法狗与巴菲特>,里面记载了许多股神巴菲特的人生经历,今天小编简单说一说关于股神 ...
- 2014巴菲特股东大会及巴菲特创业分享
沃伦·巴菲特,这位传奇人物.在美国,巴菲特被称为"先知".在中国,他更多的被喻为"股神",巴菲特在11岁时第一次购买股票以来,白手起家缔造了一个千亿规模的 ...
- 《成为沃伦·巴菲特》笔记与感想
本文首发于微信公众帐号: 一界码农(The_hard_the_luckier) 无需授权即可转载: 甚至无需保留以上版权声明-- 沃伦·巴菲特传记的纪录片 http://www.bilibili.co ...
- 读书笔记002:托尼.巴赞之快速阅读
读书笔记002:托尼.巴赞之快速阅读 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<快速阅读>之后,我们就可以可以快速提高阅读速度,保持并改善理解嗯嗯管理,通过增进了解眼睛和大脑功能 ...
- 读书笔记001:托尼.巴赞之开动大脑
读书笔记001:托尼.巴赞之开动大脑 托尼.巴赞是放射性思维与思维导图的提倡者.读完他的<开动大脑>之后,我们就可以对我们的大脑有更多的了解:大脑可以进行比我们预期多得多的工作:我们可以最 ...
- 读书笔记003:托尼.巴赞之思维导图
读书笔记003:托尼.巴赞之思维导图 托尼.巴赞的<思维导图>一书,详细的介绍了思维发展的新概念--放射性思维:如何利用思维导图实施你的放射性思维,实现你的创造性思维,从而给出一种深刻的智 ...
- 产品读书《滚雪球:巴菲特和他的财富人生》
作者简介 艾丽斯.施罗德,曾经担任世界知名投行摩根士丹利的董事总经理,因为撰写研究报告与巴菲特相识.业务上的往来使得施罗德有更多的机会与巴菲特亲密接触,她不仅是巴菲特别的忘年交,她也是第一个向巴菲特建 ...
最新文章
- android字体行距,android textview设置字体的行距和字间距
- 中国金融数字科创大赛丨神策数据客户——深圳农商银行、昆山农商银行斩获「双奖」
- Day2:html和css
- webservice / cxf 开发经验总结
- c++ console 取实时输入_灵活使用 console 让 js 调试更简单
- 哪些网站在+1s后有神奇的功能
- tp交换机管理页面_二层网管交换机的管理方法
- springmvc错误java.lang.IllegalArgumentException
- 如何通过jQuery动态设置元素CSS的样式,以及HTML中CSS “内联式”、“嵌套式”、“外联式”使用方法
- 电镜的成像原理-冷冻电镜成像技术1
- ubuntu 安装360浏览器
- Android知识点 121 —— AlarmManager与RTC唤醒
- 静态分析Android程序
- springboot配置redis(单节点)
- C# 面试EF 和mvc
- vue和java获取地理位置经纬度
- R语言笔记⑧——数据挖掘算法
- 中国企业入局AR芯片市场,提升元宇宙时代的核心竞争力
- 多条Qt开发常见问题及解决方法汇总
- 基于jquery实现table内部数据排序
热门文章
- java小游戏之捕鱼达人,学了java,妈妈不再担心我去网吧游戏厅了!
- 国服部落人数最多的服务器,魔兽7.0人口普查:国服玩家达270万,部落人数超联盟14%...
- IT职场法则七条——献给正在努力奋斗的你们
- 【黄啊码】vue-pdf预览时无法显示印章和中文字体或者乱码(简单粗暴)
- CEOI 2020, Day 2 A,B题解 CF1403A CF1403B
- 虚幻4基础操作 - 初中生学UE4第一季-丁树凯-专题视频课程
- Unity3D游戏开发之网络游戏服务器架构设计(如何做一名主程)
- vSphere web client 虚拟机生成模板快速部署
- 3D游戏引擎系列十一
- Ubuntu16.04 NVIDIA显卡驱动卸载与安装