C++进修之STL(一)—— erase和remove特异行动
2014-08-29 17:00
351 查看
C++进修之STL(一)—— erase和remove特异行动 |
2011年8月16日联系商易上海电子商务网站建设,了解更多 |
C++的STL经由过程iterator将container和algorithm分别,并经由过程functor供给高可定制性。iterator可以看作是一种契约,algorithm对iterator进行操纵,algorithm很难对container进行直接操纵,这是因为algorithm对container所知甚少,一段代码,若未哄骗操纵对象所知全部信息,将难以达到机能之极,并伴随其它各种调和现象。当然,这种“未知性”是必须的——algorithm对于真正的操纵对象container不克不及做出太多假设,若假设过多,何来一个algorithm可以感化若干不合container的妙举,STL强大威力也将受损不少。 烦琐几句,开个小头,转入正题。 先给出几个关于STL中erase和remove(remove_if等,下称remove类函数)的事实,小小复习: erase一般作为一个container的成员函数,是真正删除的元素,是物理上的删除 作为算法项目组的remove类函数,是逻辑上的删除,将被删除的元素移动到容器末尾,然后返回新的末尾,此时容器的size不变更 项目组容器供给remove类成员函数,那么代表的是真正物理意义上的删除元素 若是该容器是vector、string或者deque,应用erase-remove idiom或者erase-remove_if idiom 若是该容器是list,应用list::remove或者list:remove_if成员函数 若是该容器是一个associative container,应用asso_con::erase成员函数或者remove_copy_if连络swap等体式格式 有一些斗劲特别的容器具现,比如vector<bool>等,暂不推敲。 更多信息,可以参考《Effective STL》 综上一些信息,可以发明,STL供给给我们的“删除”语义并非真正同一,至少未达到最高层次的同一。有时辰从一种容器换为别的一种容器,修批改改总少不了。 下面,供给一个同一的接口,来删除一个容器中的元素,道理较简单,应用编译器经由过程type deduce获知容器的类型,然后经由过程type traits在编译器就可以决意函数派送决意。比如,编译器知道当前容器是list,那么就会调用list:remove相干的成员函数,机能?inline当然少不了!代码起原是一个STL的教授教化视频上得之,做了些自认为是的简单批改,当然,我的批改可能让代码“恶”了,本身简单用了些容器做测试,法度行动正确,用了trace对象跟踪代码,萍踪合适预期,当然,重在思惟的应用,真正的代码应用还须要经过多次严格测试。 1: // 2: //Source code originally MSDN Channel 9 Video 3: //Modified by techmush 4: //NOTE: the original code may be perfect, the modified version may be buggy! 5: //Modifies: add string container, add some template parameters, alert some name 6: // add some notes, code style. 7: // 8: 9: #pragma once 10: 11: #ifndef erasecontainer_h__ 12: #define erasecontainer_h__ 13: 14: #include <algorithm> 15: #include <deque> 16: #include <forward_list> 17: #include <list> 18: #include <map> 19: #include <set> 20: #include <vector> 21: #include <string> //string "as" a vector 22: #include <unordered_map> 23: #include <unordered_set> 24: 25: namespace techmush 26: { 27: namespace detail 28: { 29: //erasing behavior like vector: vector, queue, string 30: struct vector_like_tag 31: { 32: }; 33: 34: //erasing behavior like list: list, forward_list 35: struct list_like_tag 36: { 37: }; 38: 39: //erasing behaviod like set: set, map, multiset, multimap, unordered_set, unordered_map 40: //unordered_multiset, unordered_multimap 41: struct associative_like_tag 42: { 43: }; 44: 45: //type traits for containers 46: template <typename Cont> struct container_traits; 47: 48: template <typename Elem, typename Alloc> 49: struct container_traits<std::vector<Elem,Alloc> > 50: { 51: typedef vector_like_tag container_category; 52: }; 53: 54: template <typename Elem, typename Alloc> 55: struct container_traits<std::deque<Elem,Alloc> > 56: { 57: typedef vector_like_tag container_category; 58: }; 59: 60: //full specialization traits for string 61: template <> struct container_traits<std::string> 62: { 63: typedef vector_like_tag container_category; 64: }; 65: 66: 67: template <typename Elem, typename Alloc> 68: struct container_traits<std::list<Elem,Alloc> > 69: { 70: typedef list_like_tag container_category; 71: }; 72: 73: template <typename Elem, typename Alloc> 74: struct container_traits<std::forward_list<Elem,Alloc> > 75: { 76: typedef list_like_tag container_category; 77: }; 78: 79: template <typename Key, typename Pred, typename Alloc> 80: struct container_traits<std::set<Key,Pred,Alloc> > 81: { 82: typedef associative_like_tag container_category; 83: 84: }; 85: 86: //If a multiset contains duplicates, you can""t use erase() 87: //to remove only the first element of these duplicates. 88: template <typename Key, typename Pred, typename Alloc> 89: struct container_traits<std::multiset<Key,Pred,Alloc> > 90: { 91: typedef associative_like_tag container_category; 92: }; 93: 94: template <typename Key, typename Hash, typename Equal, typename Alloc> 95: struct container_traits<std::unordered_set<Key,Hash,Equal,Alloc> > 96: { 97: typedef associative_like_tag container_category; 98: }; 99: 100: template <typename Key, typename Hash, typename Equal, typename Alloc> 101: struct container_traits<std::unordered_multiset<Key,Hash,Equal,Alloc> > 102: { 103: typedef associative_like_tag container_category; 104: }; 105: 106: template <typename Key, typename Val, typename Pred, typename Alloc> 107: struct container_traits<std::map<Key,Val,Pred,Alloc> > 108: { 109: typedef associative_like_tag container_category; 110: }; 111: 112: template <typename Key, typename Val, typename Pred, typename Alloc> 113: struct container_traits<std::multimap<Key,Val,Pred,Alloc> > 114: { 115: typedef associative_like_tag container_category; 116: }; 117: 118: template <typename Key, typename Val, typename Hash, typename Equal, typename Alloc> 119: struct container_traits<std::unordered_map<Key,Val,Hash,Equal,Alloc> > 120: { 121: typedef associative_like_tag container_category; 122: }; 123: 124: template <typename Key, typename Val, typename Hash, typename Equal, typename Alloc> 125: struct container_traits<std::unordered_multimap<Key,Val,Hash,Equal,Alloc> > 126: { 127: typedef associative_like_tag container_category; 128: }; 129: 130: 131: //for vector-like containers, use the erase-remove idiom 132: template <typename Cont, typename Elem> 133: inline void erase_helper(Cont& c, const Elem& x, vector_like_tag /*ignored*/) 134: { 135: c.erase(std::remove(c.begin(), c.end(), x), c.end()); 136: } 137: 138: //for vector-like containers, use the erase-remove_if idiom 139: template <typename Cont, typename Pred> 140: inline void erase_if_helper(Cont& c, Pred p, vector_like_tag) 141: { 142: c.erase(std::remove_if(c.begin(), c.end(), p), c.end()); 143: } 144: 145: //for list-like containers, use the remove member-function 146: template <typename Cont, typename Elem> 147: inline void erase_helper(Cont& c, const Elem& x, list_like_tag) 148: { 149: c.remove(x); 150: } 151: 152: //for list-like containers, use the remove_if member-function 153: template <typename Cont, typename Pred> 154: inline void erase_if_helper(Cont& c, Pred p, list_like_tag) 155: { 156: c.remove_if(p); 157: } 158: 159: //for associative containers, use the erase member-function 160: template <typename Cont, typename Elem> 161: inline void erase_helper(Cont& c, const Elem& x, associative_like_tag) 162: { 163: c.erase(x); 164: } 165: 166: //When an element of a container is erased, all iterators that point to that 167: //element are invalidated. Once c.erase(it) reuturns, it has been invalidated. 168: template <typename Cont, typename Pred> 169: inline void erase_if_helper(Cont& c, Pred p, associative_like_tag) 170: { 171: for (auto it = c.begin(); it != c.end(); /*nothing*/) 172: { 173: if (p(*it)) 174: c.erase(it++); //Rebalance the tree 175: //Must have an iterator to the next element 176: else //of c before call erase 177: ++ it; 178: } 179: } 180: } 181: 182: //Interface function for erase 183: template <typename Cont, typename Elem> 184: inline void erase(Cont& c, const Elem& x) 185: { 186: detail::erase_helper(c, x, typename /*a type*/detail::container_traits<Cont>::container_category()); 187: } 188: 189: 190: //Interface function for erase_if 191: template <typename Cont, typename Pred> 192: inline void erase_if(Cont& c, Pred p) 193: { 194: detail::erase_if_helper(c, p, typename detail::container_traits<Cont>::container_category()); 195: } 196: } 197: #endif // erasecontainer_h__ 当然,既然选择了C++,就代表选择了折腾(这不也是种乐趣么!),若是容器内是raw pointer呢,你若是想删除,那还到手动去开释资料,万一又有异常产生,呃……好吧,应用auto_ptrs,可以么?(COAP!当然,也可以冒险应用之,重视auto_ptrs的行动特点)。嗯,应用shared_ptrs,较安然。有时辰,不得不消指针,因为我想虚多态。 |
相关文章推荐
- C++进修之STL(一)—— erase和remove特异行动
- C++复习之STL(一)—— erase和remove特异行为
- C++ STL 中 remove 和 erase 的区别 http://www.xuebuyuan.com/1422428.html
- C++ STL 中 remove 和 erase 的区别
- STL Vector remove()和erase()的使用
- vector中的删除,erase和remove的小疑惑--【STL】
- [STL] 注意erase() 和remove()
- C++中防止STL中迭代器失效——map/set等关联容器——vector/list/deque等序列容器—如何防止迭代器失效—即erase()的使用
- C++之STL(七):剩下5种算法代码分析与使用示例(remove 、rotate 、sort、lower_bound、accumulate)
- C++中防止STL中迭代器失效__map/set等关联容器vector/list/deque等序列容器_如何防止迭代器失效_即erase()的使用
- 注意C++ STL容器中erase的使用
- STL笔记(4)关于erase,remove
- STL笔记(4)关于erase,remove
- STL中remove与erase
- STL remove和erase
- STL之erase,remove
- stl 关于erase,remove,元素删除
- STL笔记(4)关于erase,remove
- STL Vector remove()和erase()的使用
- STL中的remove与erase