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}

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 会真正的把数据删除掉:

  1. // For vector, we have to call erase after remove.
  2. vector<int> v;
  3. // ....
  4. vector<int>::iterator endPos = remove(v.begin(), v.end(), 99); // Remove 99 from vector, returns last valid position.
  5. v.erase(posEnd, v.end()); // Erase all elements after posEnd.
  6.  
  7. // For list, the member function remove is enough:
  8. list<int> l;
  9. //...
  10. l.remove(99); // this will erase all 99 in the list.

2 remove, container, pointer

Item 6 中提到,在容器中放置对象指针容易混乱,这里如果对存放指针的容器调用 remove-erase idom
的话,会发生什么事情?

  1. 1: class Widget
  2. 2: {
  3. 3: public:
  4. 4: Widget();
  5. 5: virtual ~Widget();
  6. 6: bool IsCertified();
  7. 7: };
  8. 8:
  9. 9: vector<Widget*> v;
  10. 10:
  11. 11: // push lots of widget pointers to v.
  12. 12:
  13. 13: v.erase(remove(v.begin(), v.end(), not1(mem_fun(&Widget::IsCertified))), v.end());

内存泄露。

那么将第 13 行换成下面的表达式呢?

  1. 14: vector<Widget*> endPos = remove(v.begin(), v.end(), not(mem_fun(&Widget::IsCertified)));
  2. 15: for_each(endPos, v.end(), [](Widget* pw){if(pw) delete pw;});
  3. 16: v.erase(endPos, v.end());

第 14 行将所有的 endPos 之后的指针先释放,然后再去 erase。前面刚刚提过, remove 不会保证返回的迭代器之后的元素都为无效值,第 14 行有可能会将本该保留的对象给释放掉,还有可能会将该释放的不释放。结果可能会 Crash 或者内存泄露。

我们应该保证在 remove 过程中,一旦发现不合要求的数据,马上将其删除,例如下面的例子:

  1. #include <vector>
  2. #include <iterator>
  3. #include <algorithm>
  4. #include <iostream>
  5. #include <stdio.h>
  6.  
  7. using namespace std;
  8.  
  9. class Widget
  10. {
  11. public:
  12. Widget(int i);
  13. virtual ~Widget();
  14. bool IsCertified();
  15. void Show();
  16. private:
  17. int m_i;
  18. };
  19.  
  20. /* See description in header file. */
  21. Widget::Widget(int i)
  22. : m_i(i)
  23. {
  24. }
  25.  
  26. /* See description in header file. */
  27. Widget::~Widget()
  28. {
  29. printf ("Deleting Obj: %p, value: %d\n", this, m_i);
  30. }
  31.  
  32. /* See description in header file. */
  33. bool Widget::IsCertified()
  34. {
  35. return m_i % 2 == 0;
  36. }
  37.  
  38. /* See description in header file. */
  39. void Widget::Show()
  40. {
  41. printf ("\tObj: %p, value: %d\n", this, m_i);
  42. }
  43.  
  44. bool DeleteIfUncitified(Widget* p)
  45. {
  46. if (p && !p->IsCertified())
  47. {
  48. delete p;
  49. return true;
  50. }
  51. return false;
  52. }
  53.  
  54. int main(int argc, char *argv[])
  55. {
  56. vector<Widget*> v;
  57. for (int i = 0; i < 20; ++i)
  58. {
  59. Widget* p = new Widget(i);
  60. v.push_back(p);
  61. }
  62.  
  63. random_shuffle(v.begin(), v.end());
  64.  
  65. printf ("Before remove, size: %lu, contents:\n", v.size());
  66. for_each(v.begin(), v.end(),
  67. [](Widget* p){
  68. if (p) p->Show();
  69. else printf("Obj is Null");});
  70. printf ("\nNow removing...\n");
  71. v.erase(remove_if(v.begin(), v.end(), DeleteIfUncitified), v.end());
  72. printf ("\nAfter remove, size: %lu, contents:\n", v.size());
  73. for_each(v.begin(), v.end(),
  74. [](Widget* p){
  75. if (p) p->Show();
  76. else printf("Obj is Null");});
  77.  
  78. return 0;
  79. }

其输出为:

  1. Welcome to the Emacs shell
  2.  
  3. ~/tmp $ ./test
  4. Before remove, size: 20, contents:
  5. Obj: 0x7f8b31c038d0, value: 19
  6. Obj: 0x7f8b31c03870, value: 3
  7. Obj: 0x7f8b31c039e0, value: 14
  8. Obj: 0x7f8b31c039f0, value: 15
  9. Obj: 0x7f8b31c03890, value: 10
  10. Obj: 0x7f8b31c03850, value: 2
  11. Obj: 0x7f8b31c03900, value: 6
  12. Obj: 0x7f8b31c038b0, value: 17
  13. Obj: 0x7f8b31c03920, value: 8
  14. Obj: 0x7f8b31c038a0, value: 4
  15. Obj: 0x7f8b31c039c0, value: 12
  16. Obj: 0x7f8b31c03910, value: 7
  17. Obj: 0x7f8b31c038f0, value: 5
  18. Obj: 0x7f8b31c039b0, value: 11
  19. Obj: 0x7f8b31c03860, value: 1
  20. Obj: 0x7f8b31c03880, value: 9
  21. Obj: 0x7f8b31c03840, value: 0
  22. Obj: 0x7f8b31c03a00, value: 16
  23. Obj: 0x7f8b31c039d0, value: 13
  24. Obj: 0x7f8b31c038c0, value: 18
  25.  
  26. Now removing...
  27. Deleting Obj: 0x7f8b31c038d0, value: 19
  28. Deleting Obj: 0x7f8b31c03870, value: 3
  29. Deleting Obj: 0x7f8b31c039f0, value: 15
  30. Deleting Obj: 0x7f8b31c038b0, value: 17
  31. Deleting Obj: 0x7f8b31c03910, value: 7
  32. Deleting Obj: 0x7f8b31c038f0, value: 5
  33. Deleting Obj: 0x7f8b31c039b0, value: 11
  34. Deleting Obj: 0x7f8b31c03860, value: 1
  35. Deleting Obj: 0x7f8b31c03880, value: 9
  36. Deleting Obj: 0x7f8b31c039d0, value: 13
  37.  
  38. After remove, size: 10, contents:
  39. Obj: 0x7f8b31c039e0, value: 14
  40. Obj: 0x7f8b31c03890, value: 10
  41. Obj: 0x7f8b31c03850, value: 2
  42. Obj: 0x7f8b31c03900, value: 6
  43. Obj: 0x7f8b31c03920, value: 8
  44. Obj: 0x7f8b31c038a0, value: 4
  45. Obj: 0x7f8b31c039c0, value: 12
  46. Obj: 0x7f8b31c03840, value: 0
  47. Obj: 0x7f8b31c03a00, value: 16
  48. Obj: 0x7f8b31c038c0, value: 18
  49. ~/tmp $

Effective STL 学习笔记 32 ~ 33的更多相关文章

  1. Effective STL 学习笔记 39 ~ 41

    Effective STL 学习笔记 39 ~ 41 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...

  2. 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 ...

  3. Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据

    Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据 */--> div.org-src-container { font-size: 85%; font-fam ...

  4. Effective STL 学习笔记 31:排序算法

    Effective STL 学习笔记 31:排序算法 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...

  5. Effective STL 学习笔记 Item 30: 保证目标区间足够大

    Effective STL 学习笔记 Item 30: 保证目标区间足够大 */--> div.org-src-container { font-size: 85%; font-family: ...

  6. 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 ...

  7. Effective STL 学习笔记: Item 22 ~ 24

    Effective STL 学习笔记: Item 22 ~ 24 */--> div.org-src-container { font-size: 85%; font-family: monos ...

  8. Effective STL 学习笔记 Item 21:Comparison Function 相关

    Effective STL 学习笔记 Item 21:Comparison Function 相关 */--> div.org-src-container { font-size: 85%; f ...

  9. Effective STL 学习笔记:19 ~ 20

    Effective STL 学习笔记:19 ~ 20 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...

随机推荐

  1. 利用机器学习实现微信小程序-加减大师自动答题

    之前有看到微信小程序<跳一跳>别人用python实现自动运行,后来看到别人用hash码实现<加减大师>的自动答题领取娃娃,最近一直在研究深度学习,为啥不用机器学习实现呢?不就是 ...

  2. 华为手机不能连接android studio进行调试的解决办法

    出现情景:在开启了usb debugging(usb调试模式)后,AS(android studio)还是找不到真机. 解决办法:下载驱动精灵,检测是否安装了huawei的usb驱动,如果没有,安装成 ...

  3. [Java] I/O底层原理之一:字符流、字节流及其源码分析

    关于 I/O 的类可以分为四种: 关于字节的操作:InputStream 和 OutPutStream: 关于字符的操作:Writer 和 Reader: 关于磁盘的操作:File: 关于网络的操作: ...

  4. NGINX配置详解及应用

    目录 NGINX    1 1.1    目录结构    1 1.2    基础配置    1 1.3    location    5 1.4    虚拟主机    5 1.5    状态模块    ...

  5. alertdialog 设置最大高度

    设置最大高度,有很多方法,我个人比较喜欢的是下面这种方式 ,这里的view即添加到 view.addOnLayoutChangeListener(new View.OnLayoutChangeList ...

  6. Java并发编程原理与实战三十六:阻塞队列&消息队列

    一.阻塞队列 1.阻塞队列BlockingQueue ---->可以理解成生产者消费者的模式---->消费者要等待到生产者生产出来产品.---->而非阻塞队列ConcurrentLi ...

  7. 微服务深入浅出(4)-- 负载均衡Ribbon

    Spring Cloud中可以使用RestTemplate+Ribbon的解决方案来将负载均衡以代码的形式封装到客户端中. 通过查阅官方文档可以知道,只需要在程序的IoC容器中注入一个restTemp ...

  8. caffe的特殊层

    每次写博客都带有一定的目的,在我看来这是一个记录的过程,所以尽量按照循序渐进的顺序逐步写,前面介绍的CNN层应该是非常常用的,这篇博客介绍一下某些特殊的layer,但是由于特殊的layer都带有一定的 ...

  9. HSL

    说明: HSL(H,S,L) 取值: H: Hue(色调).0(或360)表示红色,120表示绿色,240表示蓝色,也可取其他数值来指定颜色.取值为:0 - 360 S: Saturation(饱和度 ...

  10. 【蓝桥杯单片机11】单总线温度传感器DS18B20的基本操作

    [蓝桥杯单片机11]单总线温度传感器DS18B20的基本操作 广东职业技术学院 欧浩源 单总线数字温度传感器DS18B20几乎成了各类单片机甚至ARM实验板的标配模块来,在蓝桥杯的往届省赛和国赛中,这 ...