Effective STL 学习笔记 32 ~ 33
Effective STL 学习笔记 32 ~ 33
*/-->
div.org-src-container {
font-size: 85%;
font-family: monospace;
}
pre.src {
background-color:#f8f4d7
}
p {font-size: 15px}
li {font-size: 15px}
Table of Contents
1 记得 Remove 后要 Erase
Item 9 中已经提到过,如果真的想要用 remove 从容器中删除元素,必须要在 remove 之后使用 erase
。其原因在于: remove 接受的参数是通用的迭代器,而不是容器,它不知道容器的任何信息,也就无法从容器中删除元素: remove doesn't really remove anything, because it can't.
remove 只保证在其返回的迭代器之前的元素为有效数据(符合条件的数据),但它既无法删除被 remove
的数据,也不能保证返回的迭代器之后的数据位无效数据(不符合条件的数据)。这一点与某些容器内置的 remove member function 不一样:这些 member function 会真正的把数据删除掉:
- // For vector, we have to call erase after remove.
- vector<int> v;
- // ....
- vector<int>::iterator endPos = remove(v.begin(), v.end(), 99); // Remove 99 from vector, returns last valid position.
- v.erase(posEnd, v.end()); // Erase all elements after posEnd.
- // For list, the member function remove is enough:
- list<int> l;
- //...
- l.remove(99); // this will erase all 99 in the list.
2 remove, container, pointer
Item 6 中提到,在容器中放置对象指针容易混乱,这里如果对存放指针的容器调用 remove-erase idom
的话,会发生什么事情?
- 1: class Widget
- 2: {
- 3: public:
- 4: Widget();
- 5: virtual ~Widget();
- 6: bool IsCertified();
- 7: };
- 8:
- 9: vector<Widget*> v;
- 10:
- 11: // push lots of widget pointers to v.
- 12:
- 13: v.erase(remove(v.begin(), v.end(), not1(mem_fun(&Widget::IsCertified))), v.end());
内存泄露。
那么将第 13 行换成下面的表达式呢?
- 14: vector<Widget*> endPos = remove(v.begin(), v.end(), not(mem_fun(&Widget::IsCertified)));
- 15: for_each(endPos, v.end(), [](Widget* pw){if(pw) delete pw;});
- 16: v.erase(endPos, v.end());
第 14 行将所有的 endPos 之后的指针先释放,然后再去 erase。前面刚刚提过, remove 不会保证返回的迭代器之后的元素都为无效值,第 14 行有可能会将本该保留的对象给释放掉,还有可能会将该释放的不释放。结果可能会 Crash 或者内存泄露。
我们应该保证在 remove 过程中,一旦发现不合要求的数据,马上将其删除,例如下面的例子:
- #include <vector>
- #include <iterator>
- #include <algorithm>
- #include <iostream>
- #include <stdio.h>
- using namespace std;
- class Widget
- {
- public:
- Widget(int i);
- virtual ~Widget();
- bool IsCertified();
- void Show();
- private:
- int m_i;
- };
- /* See description in header file. */
- Widget::Widget(int i)
- : m_i(i)
- {
- }
- /* See description in header file. */
- Widget::~Widget()
- {
- printf ("Deleting Obj: %p, value: %d\n", this, m_i);
- }
- /* See description in header file. */
- bool Widget::IsCertified()
- {
- return m_i % 2 == 0;
- }
- /* See description in header file. */
- void Widget::Show()
- {
- printf ("\tObj: %p, value: %d\n", this, m_i);
- }
- bool DeleteIfUncitified(Widget* p)
- {
- if (p && !p->IsCertified())
- {
- delete p;
- return true;
- }
- return false;
- }
- int main(int argc, char *argv[])
- {
- vector<Widget*> v;
- for (int i = 0; i < 20; ++i)
- {
- Widget* p = new Widget(i);
- v.push_back(p);
- }
- random_shuffle(v.begin(), v.end());
- printf ("Before remove, size: %lu, contents:\n", v.size());
- for_each(v.begin(), v.end(),
- [](Widget* p){
- if (p) p->Show();
- else printf("Obj is Null");});
- printf ("\nNow removing...\n");
- v.erase(remove_if(v.begin(), v.end(), DeleteIfUncitified), v.end());
- printf ("\nAfter remove, size: %lu, contents:\n", v.size());
- for_each(v.begin(), v.end(),
- [](Widget* p){
- if (p) p->Show();
- else printf("Obj is Null");});
- return 0;
- }
其输出为:
- Welcome to the Emacs shell
- ~/tmp $ ./test
- Before remove, size: 20, contents:
- Obj: 0x7f8b31c038d0, value: 19
- Obj: 0x7f8b31c03870, value: 3
- Obj: 0x7f8b31c039e0, value: 14
- Obj: 0x7f8b31c039f0, value: 15
- Obj: 0x7f8b31c03890, value: 10
- Obj: 0x7f8b31c03850, value: 2
- Obj: 0x7f8b31c03900, value: 6
- Obj: 0x7f8b31c038b0, value: 17
- Obj: 0x7f8b31c03920, value: 8
- Obj: 0x7f8b31c038a0, value: 4
- Obj: 0x7f8b31c039c0, value: 12
- Obj: 0x7f8b31c03910, value: 7
- Obj: 0x7f8b31c038f0, value: 5
- Obj: 0x7f8b31c039b0, value: 11
- Obj: 0x7f8b31c03860, value: 1
- Obj: 0x7f8b31c03880, value: 9
- Obj: 0x7f8b31c03840, value: 0
- Obj: 0x7f8b31c03a00, value: 16
- Obj: 0x7f8b31c039d0, value: 13
- Obj: 0x7f8b31c038c0, value: 18
- Now removing...
- Deleting Obj: 0x7f8b31c038d0, value: 19
- Deleting Obj: 0x7f8b31c03870, value: 3
- Deleting Obj: 0x7f8b31c039f0, value: 15
- Deleting Obj: 0x7f8b31c038b0, value: 17
- Deleting Obj: 0x7f8b31c03910, value: 7
- Deleting Obj: 0x7f8b31c038f0, value: 5
- Deleting Obj: 0x7f8b31c039b0, value: 11
- Deleting Obj: 0x7f8b31c03860, value: 1
- Deleting Obj: 0x7f8b31c03880, value: 9
- Deleting Obj: 0x7f8b31c039d0, value: 13
- After remove, size: 10, contents:
- Obj: 0x7f8b31c039e0, value: 14
- Obj: 0x7f8b31c03890, value: 10
- Obj: 0x7f8b31c03850, value: 2
- Obj: 0x7f8b31c03900, value: 6
- Obj: 0x7f8b31c03920, value: 8
- Obj: 0x7f8b31c038a0, value: 4
- Obj: 0x7f8b31c039c0, value: 12
- Obj: 0x7f8b31c03840, value: 0
- Obj: 0x7f8b31c03a00, value: 16
- Obj: 0x7f8b31c038c0, value: 18
- ~/tmp $
(转载请注明出处,使用许可:署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议 。)
Effective STL 学习笔记 32 ~ 33的更多相关文章
- Effective STL 学习笔记 39 ~ 41
Effective STL 学习笔记 39 ~ 41 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...
- Effective STL 学习笔记 Item 38 : Design functor classes for pass-by-value
Effective STL 学习笔记 Item 38 : Design functor classes for pass-by-value */--> div.org-src-container ...
- Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据
Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据 */--> div.org-src-container { font-size: 85%; font-fam ...
- Effective STL 学习笔记 31:排序算法
Effective STL 学习笔记 31:排序算法 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...
- Effective STL 学习笔记 Item 30: 保证目标区间足够大
Effective STL 学习笔记 Item 30: 保证目标区间足够大 */--> div.org-src-container { font-size: 85%; font-family: ...
- Effective STL 学习笔记 Item 26: Prefer Iterator to reverse_iterator and const_rever_itertor
Effective STL 学习笔记 Item 26: Prefer Iterator to reverse_iterator and const_rever_itertor */--> div ...
- Effective STL 学习笔记: Item 22 ~ 24
Effective STL 学习笔记: Item 22 ~ 24 */--> div.org-src-container { font-size: 85%; font-family: monos ...
- Effective STL 学习笔记 Item 21:Comparison Function 相关
Effective STL 学习笔记 Item 21:Comparison Function 相关 */--> div.org-src-container { font-size: 85%; f ...
- Effective STL 学习笔记:19 ~ 20
Effective STL 学习笔记:19 ~ 20 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...
随机推荐
- 利用机器学习实现微信小程序-加减大师自动答题
之前有看到微信小程序<跳一跳>别人用python实现自动运行,后来看到别人用hash码实现<加减大师>的自动答题领取娃娃,最近一直在研究深度学习,为啥不用机器学习实现呢?不就是 ...
- 华为手机不能连接android studio进行调试的解决办法
出现情景:在开启了usb debugging(usb调试模式)后,AS(android studio)还是找不到真机. 解决办法:下载驱动精灵,检测是否安装了huawei的usb驱动,如果没有,安装成 ...
- [Java] I/O底层原理之一:字符流、字节流及其源码分析
关于 I/O 的类可以分为四种: 关于字节的操作:InputStream 和 OutPutStream: 关于字符的操作:Writer 和 Reader: 关于磁盘的操作:File: 关于网络的操作: ...
- NGINX配置详解及应用
目录 NGINX 1 1.1 目录结构 1 1.2 基础配置 1 1.3 location 5 1.4 虚拟主机 5 1.5 状态模块 ...
- alertdialog 设置最大高度
设置最大高度,有很多方法,我个人比较喜欢的是下面这种方式 ,这里的view即添加到 view.addOnLayoutChangeListener(new View.OnLayoutChangeList ...
- Java并发编程原理与实战三十六:阻塞队列&消息队列
一.阻塞队列 1.阻塞队列BlockingQueue ---->可以理解成生产者消费者的模式---->消费者要等待到生产者生产出来产品.---->而非阻塞队列ConcurrentLi ...
- 微服务深入浅出(4)-- 负载均衡Ribbon
Spring Cloud中可以使用RestTemplate+Ribbon的解决方案来将负载均衡以代码的形式封装到客户端中. 通过查阅官方文档可以知道,只需要在程序的IoC容器中注入一个restTemp ...
- caffe的特殊层
每次写博客都带有一定的目的,在我看来这是一个记录的过程,所以尽量按照循序渐进的顺序逐步写,前面介绍的CNN层应该是非常常用的,这篇博客介绍一下某些特殊的layer,但是由于特殊的layer都带有一定的 ...
- HSL
说明: HSL(H,S,L) 取值: H: Hue(色调).0(或360)表示红色,120表示绿色,240表示蓝色,也可取其他数值来指定颜色.取值为:0 - 360 S: Saturation(饱和度 ...
- 【蓝桥杯单片机11】单总线温度传感器DS18B20的基本操作
[蓝桥杯单片机11]单总线温度传感器DS18B20的基本操作 广东职业技术学院 欧浩源 单总线数字温度传感器DS18B20几乎成了各类单片机甚至ARM实验板的标配模块来,在蓝桥杯的往届省赛和国赛中,这 ...