<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://mediawiki.zeropage.org/index.php?action=history&amp;feed=atom&amp;title=EffectiveSTL%2FContainer</id>
	<title>EffectiveSTL/Container - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://mediawiki.zeropage.org/index.php?action=history&amp;feed=atom&amp;title=EffectiveSTL%2FContainer"/>
	<link rel="alternate" type="text/html" href="https://mediawiki.zeropage.org/index.php?title=EffectiveSTL/Container&amp;action=history"/>
	<updated>2026-05-14T15:03:52Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.8</generator>
	<entry>
		<id>https://mediawiki.zeropage.org/index.php?title=EffectiveSTL/Container&amp;diff=31490&amp;oldid=prev</id>
		<title>imported&gt;Unknown at 05:23, 7 February 2021</title>
		<link rel="alternate" type="text/html" href="https://mediawiki.zeropage.org/index.php?title=EffectiveSTL/Container&amp;diff=31490&amp;oldid=prev"/>
		<updated>2021-02-07T05:23:10Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;* STL을 구성하는 핵심 요소에는 여러 가지가 있다.(Iterator, Generic Algorithm, Container 등등). 역시 가장 핵심적이고, 조금만 알아도 쓸수 있고, 편하게 쓸수 있는 것은 Container다. Container는 Vector, List, Deque 과 같이 데이터를 담는 그릇과 같은 Object라고 보면 된다.&lt;br /&gt;
* STL의 Container들의 장점이라고 한다면, 역시 유연성, 메모리 관리 알아서 하기, 자신이 알아서 늘었다 즐었다 하기 등등이 있겠다. 또한 인터페이스가 이거나 저거나 비슷비슷해서 하나만 공부하면, 쉽게 다른것도 쓸수 있다는 것도 또 하나의 장점이 될수 있겠다.&lt;br /&gt;
* 큰 1장 Containers에서는 상황에 맞는 적절한 Container 고르는 법, 효율성 극대화 하기 등등을 다룬다.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
= Item1. Choose your containers with care. =&lt;br /&gt;
== STL이 지원하는 Containers ==&lt;br /&gt;
* Sequence Containers - vector, deque, list, string( vector&amp;amp;lt;char&amp;amp;gt; ) 등등&lt;br /&gt;
* Associative Containers - set, multiset, map, multimap 등등&lt;br /&gt;
* 그 외에 Non Standard라고 써있는게 있긴 한데, 잘 안쓰는 것 같다. 혹시라도 나중에 중요성이 부각되면 다시 봐야겠다. 딴게 급하니 일단.. AfterCheck&lt;br /&gt;
* vector가 좋다고 써있다. 잘 쓰자. 가끔가다 시간,저장공간 등등에 있어서 Associative Containers를 압도할때도 있다고 한다.&lt;br /&gt;
** vector 는 Sequence Container 니까 보통 Associative Container 들(주로 Map)보다 메모리낭비가 덜함. 그대신 하나 단위 검색을 할때에는 Associative Container 들이 더 빠른 경우가 있음. (예를 들어 전화번호들을 저장한 container 에서 024878113 을 찾는다면.? map 의 경우는 바로 해쉬함수를 이용, 한큐에 찾지만, Sequence Container 들의 경우 처음부터 순차적으로 좌악 검색하겠지.) --&amp;amp;#91;1002&amp;amp;#93;&lt;br /&gt;
&lt;br /&gt;
== vector, deque, list 고르는 팁 ==&lt;br /&gt;
* vector는 무난하게 쓰고 싶을때&lt;br /&gt;
* list는 중간에서 삽입, 삭제가 자주 일어날때&lt;br /&gt;
* deque는 종단점(시작과 끝)에서 삽입, 삭제가 자주 일어날때&lt;br /&gt;
== Contiguous-memory Containers &amp;amp; Node-based Containers ==&lt;br /&gt;
* 전자는 배열을 기반으로 하는 Container(즉, 동적 메모리 할당을 할때 할당된 메모리들이 연속적이 된다), 후자는 노드를 기반으로 하는 Container(노드의 경우는 반드시 연속적인 메모리가 아닐 수 있다.)다. 노드가 뭔지는 링크드 리스트를 짜보면 알게 된다.&lt;br /&gt;
* 전자에는 vector, string, deque 등이 있다. 뭔가 또 복잡한 말이 있긴 한데 그냥 넘어가자. 대충 insert, delete가 일어나면 기존의 원소가 이동한다는 말 같다.&lt;br /&gt;
* 후자에는 list 등이 있다. 노드는 그냥 포인터만 바꿔 주면 insert, delete가 자유자재로 된다는거 다 알것이다.&lt;br /&gt;
== STL Container 고르는 팁 ==&lt;br /&gt;
* 양끝에서 insert, delete 하려면? Associative Containers는 쓰면 안된다.&lt;br /&gt;
* Random Access Iterator(임의 접근 반복자)가 필요하다면, vector, deque, string 써야 한다. (rope란것도 있네), Bidirectional Iterator(양방향 반복자)가 필요하다면, slist는 쓰면 안된다.(당연하겠지) Hashed Containers 또 쓰지 말랜다.&lt;br /&gt;
* Insert, Delete 할때 원소의 인덱스 위치가 변하면 안된다? 그러면 Contiguous-memory Containers는 쓰면 안된다. (해당 원소의 인덱스 위치가 변한다.)&lt;br /&gt;
* Search 속도가 중요하다면 Hashed Containers, Sorted Vector, Associative Containers를 쓴다. (바로 인덱스로 접근, 상수 검색속도)&lt;br /&gt;
* Insert, Delete를 효율적으로 쓰려면, Node Based Containers를 쓰자.&lt;br /&gt;
* Iterator, Pointer, Reference 갱신을 최소화 하려면 Node Based Containers를 쓴다. &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Item2. Beware the illusion of container-independant code. =&lt;br /&gt;
== 완벽한 Container 독립적인 코드 작성은 불가능? ==&lt;br /&gt;
* Standard Contiguois-memory Container들은 임의접근 연산자 []을 지원하지만, 다른건 지원하지 않는다. &lt;br /&gt;
* Standard Node-based Container들은 양방향 반복자(bidirectional Iterator)를 지원한다.&lt;br /&gt;
* 결국 이 코드에서 이 컨테이너에서 작동하는 함수를 썼는데, 컨테이너를 같은 계열의 것으로 바꾸면 좋겠지만, 성향이 다른걸로 바꾸면--; 많이 고쳐야 할것이다.&lt;br /&gt;
* 각각의 컨테이너는 장점과 단점을 가지고 있다. 고르는 능력을 기르자.&lt;br /&gt;
   &amp;#039;&amp;#039;STL Tutorial and Refereince 를 보면, 일부러 해당 Container 에게 최적화된 메소드들만 지원한다고 써있었던 기억. 예를 든다면, Vector 의 경우 push_front 같은 것이 없다. (만일 vector에 push_front 를 한다면? push_front 될때마다 매번 기존의 원소들 위치가 바뀐다.) --&amp;amp;#91;1002&amp;amp;#93;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
== 그나마 고치기 쉽게 하는 팁들 ==&lt;br /&gt;
* typedef을 쓰자. &lt;br /&gt;
 vector&amp;amp;lt;Type&amp;amp;gt;::itarator // typedef vector&amp;amp;lt;Type&amp;amp;gt;::iterator VTIT 이런식으로 바꿀수 있다. 앞으로는 저렇게 길게 쓰지 않고도 VIIT 이렇게 쓸수 있다.&lt;br /&gt;
* Encapsulization을 잘 하자. 바뀌는 것에 대한 충격이 줄어들 것이다.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Item3. Make copying cheap and correct for objects in containers. =&lt;br /&gt;
== STL way ==&lt;br /&gt;
* 컨테이너에 넣을 때나 뺄 때, 복사를 한다.&lt;br /&gt;
* 컨테이너에 Object를 넣을때에는, 그 Object의 복사 생성자(const reference)와, 대입 연산자를 재정의(const reference) 해주자. 안그러면 복사로 인한 엄청난 낭비를 보게 될것이다.&lt;br /&gt;
&lt;br /&gt;
== 상속받은 객체를 넣을때의 문제점 ==&lt;br /&gt;
* Slicing에러&lt;br /&gt;
 vector&amp;amp;lt;Widget&amp;amp;gt; vw;&lt;br /&gt;
 &lt;br /&gt;
 class SpecialWidget : public Widget ...&lt;br /&gt;
 &lt;br /&gt;
 SpecialWidget sw;&lt;br /&gt;
 &lt;br /&gt;
 vw.push_back(sw) // 어떻게 될까. 복사되면서 SpecialWidget만의 특수성은 제거되고, Widget의 특성만 남게 된다.&lt;br /&gt;
* 해결책으론 가상함수 등등이 있다. 하지만 더 좋은 방법이 있다.&lt;br /&gt;
&lt;br /&gt;
== 해결책 ==&lt;br /&gt;
* 컨테이너에 값을 넣지 말고, 포인터를 넣는 것이다.&lt;br /&gt;
 vector&amp;amp;lt;Widget*&amp;amp;gt; vw;&lt;br /&gt;
 vw.push_back(new SpecialWidget); // 잘된다.&lt;br /&gt;
* 하지만 역시 내가 delete해줘야 한다는 단점이 있다. 대안으로 smart pointers라는게 있다.(이게 뭘까)&lt;br /&gt;
   [[MoreEffectiveC++/Techniques1of3]] 의 Item 28 을 봐라. 영문을 보는것이 더 좋을것이다. [[MoreEffectiveC++]] 의 전자책과 아날로그 모두다 소장하고 있으니 필요하면 말하고, 나도 이 책 정리 할려고 했는데, 참여하도록 노력하마 --[[상민]]&lt;br /&gt;
&lt;br /&gt;
== Why copy? ==&lt;br /&gt;
* 불필요한 객체의 복사를 막기 위해 디자인 되어있다.(잘 이해가 안간다.)&lt;br /&gt;
* 내가 요구할때만 그만큼 많은 공간을 할당한다.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Item4. Call empty instead of checking size() against zero. =&lt;br /&gt;
* 컨테이너에 하나도 안들었다는것을 가정할때 size() == 0 이것보다 empty() 가 더 좋다고 한다.&lt;br /&gt;
* empty()는 상수 시간에 수행이 가능하고, size()는 선형 시간에 수행이 가능하다.&lt;br /&gt;
* 고로 empty() 쓰자. &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Item5. Prefer range member functions to their single-element counterparts. =&lt;br /&gt;
* 범위 가지고 노는 메소드가 하나씩 가지고 노는 메소드보다 우월하다. 수행시간의 차이가 있는듯하다.&lt;br /&gt;
== a 컨테이너에 있는 내용의 뒷부분의 절반을 b라는 벡터 컨테이너에 넣고 싶다면, 어떻게 해야할까? ==&lt;br /&gt;
* STL에 익숙하지 않다면 아마도 다음과 같이 할 것이다.&lt;br /&gt;
 // 명시적인 반복문을 쓴다.&lt;br /&gt;
 vector&amp;amp;lt;Object&amp;amp;gt; a,b;&lt;br /&gt;
 &lt;br /&gt;
 b.clear();&lt;br /&gt;
 &lt;br /&gt;
 for(vector&amp;amp;lt;Object&amp;amp;gt;::const_itarator VWCI = a.begin() + a.size()/2 ; VWCI != a.end() ; ++VWCI)&lt;br /&gt;
 	b.push_back(*VWCI)&lt;br /&gt;
&lt;br /&gt;
* 약간 익숙한 사람이라면..&lt;br /&gt;
 // copy 알고리즘을 이용한다.&lt;br /&gt;
 vector&amp;amp;lt;Object&amp;amp;gt; a,b;&lt;br /&gt;
 &lt;br /&gt;
 b.clear();&lt;br /&gt;
 copy( a.begin() + a.size() / 2, a.end(), back_inserter(b)) ;&lt;br /&gt;
&lt;br /&gt;
* 어느 정도 알고, 익숙한 사람이면 다음과 같이..&lt;br /&gt;
 // assign 메소드를 사용한다.&lt;br /&gt;
 vector&amp;amp;lt;Object&amp;amp;gt; a,b;&lt;br /&gt;
 &lt;br /&gt;
 b.assign(a.begin() + a.size() / 2, a.end());&lt;br /&gt;
 &lt;br /&gt;
* 이 네 가지 방법을 보자. 첫번째 두번째 방법은 루프를 사용한다. 두번째 방법에 루프가 어딨냐고 물으면 나는 모른다. copy 알고리즘 내부에서 루프를 사용한단다. 하지만 assign 메소드는 루프를 사용하지 않고 한번에 짠! 해주는거 같다.&lt;br /&gt;
&lt;br /&gt;
* copy, push_back 이런것은 넣어줄때 insert iterator를 사용한다. 즉, 하나 넣고 메모리 할당 해주고, 객체 복사하고(큰 객체면... --; 묵념), 또 하나 넣어주고 저 짓하고.. 이런것이다. 하지만 assign은 똑같은 작업을 한번에 짠~, 만약 100개의 객체를 넣는다면 assign은 copy이런것보다 1/100 밖에 시간이 안걸린다는 것이다.(정확하진 않겠지만.. 뭐 그러하다.)&lt;br /&gt;
&lt;br /&gt;
* 또 하나의 문제점, insert 메소드는 실행할때마다 새로운 공간을 할당하기 위해 하나씩 밀린다. 만약 컨테이너가 n개의 객체를 가지고 있고, 거기다 m개의 객체를 insert로 넣으면.. n*m만큼 뒤로 땡기느라 시간을 낭비하게 된다. int같은 기본 자료형이면 괜찮을지도 모르지만.. 만약에 객체가 큰 경우라면, 대입 연산자, 복사 생성자 이런것도 저만큼 호출하게 된다. 미친다. &lt;br /&gt;
&lt;br /&gt;
* range 멤버 메소드는 주어진 두개의 반복자로 크기를 계산해서 한번에 옮기고 넣는다. 벡터를 예로 들면, 만약에 주어진 공간이 꽉 찼을때, insert를 수행하면, 새로운 공간 할당해서 지금의 내용들과, 넣으려는 것들을 그리로 옮기고 지금 있는걸 지우는 작업이 수행된다. 이짓을 100번 해보라, 컴퓨터가 상당히 기분나빠할지도 모른다. 하지만 range 멤버 메소드는 미리 늘려야 할 크기를 알기 때문에 한번만 하면 된다. &lt;br /&gt;
&lt;br /&gt;
* 성능 따지기 골치 아픈 사람이라도, range 시리즈가 하나씩 시리즈보다 타이핑 양이 적다는 걸 알것이다.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Item6. Be alery for c++&amp;#039;s most vexing parse =&lt;br /&gt;
== 문제점? ==&lt;br /&gt;
* 아직까지도 STL을 완벽하게 지원하는 컴파일러는 존재하지 않는다.&lt;br /&gt;
* 잊어버리고 있었던 클래스의 생성자에 관한..&lt;br /&gt;
 class Widget {...};    // 디폴트 생성자가 있다고 가정&lt;br /&gt;
 Widget a               // 맞다.&lt;br /&gt;
 Widget b()             // 과연?&lt;br /&gt;
* Widget b() 이것은 Widget형의 객체를 리턴해주는 b라는 이름을 가진 함수다. 이것과 관련해 파싱 에러가 자주 일어난다고 한다.&lt;br /&gt;
&lt;br /&gt;
== 예제 : ints.dat 에 저장되어 있는 정수들을 읽어서 list&amp;amp;lt;int&amp;amp;gt; data에 쓰는 작업을 한다. ==&lt;br /&gt;
&lt;br /&gt;
 ifstream dataFile(&amp;quot;ints.dat&amp;quot;);&lt;br /&gt;
 list&amp;amp;lt;int&amp;amp;gt; data(ifstream_iterator&amp;amp;lt;int&amp;amp;gt;(dataFile),ifstream_iterator&amp;amp;lt;int&amp;amp;gt;());     // 이런 방법도 있군. 난 맨날 돌려가면서 넣었는데..--;&lt;br /&gt;
&lt;br /&gt;
* 왠지는 모르겠지만 두번째 문장은 작동하지 않는다. 위에서 제기한 문제 때문(괄호에 관련된)이다. 별루 중요한 것 같진 않으니 그냥 넘어감. 그래도 해결책은..&lt;br /&gt;
&lt;br /&gt;
== 해결책 ==&lt;br /&gt;
 ifstream dataFile(&amp;quot;ints.dat&amp;quot;);&lt;br /&gt;
 ifstream_iterator&amp;amp;lt;int&amp;amp;gt; dataBegin(dataFile);&lt;br /&gt;
 ifstream_iterator&amp;amp;lt;int&amp;amp;gt; dataEnd;&lt;br /&gt;
 &lt;br /&gt;
 list&amp;amp;lt;int&amp;amp;gt; data(dataBegin, dataEnd);         // 요런식으로 써주자.&lt;br /&gt;
&lt;br /&gt;
== 잡담 ==&lt;br /&gt;
* C++이 이렇게 애매한줄은 몰랐다.&lt;br /&gt;
* STL에서 반복자로 돌리는건 표준 스타일이란다. 그렇게 하도록 하자.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Item7. When using containers of newed pointers, remember to delete the pointers before the container is destroyed =&lt;br /&gt;
== 서론 ==&lt;br /&gt;
* 누누히 강조했던 new로 만든거 넣었으면, delete 해주자는 것이다.&lt;br /&gt;
* 컨테이너가 파괴될때 포인터는 지워주겠지만, 포인터가 가리키는 객체는 destroy되지 않는다.(Detected Memory Leaks!)&lt;br /&gt;
== 예제 ==&lt;br /&gt;
 vector&amp;amp;lt;Object*&amp;amp;gt; v;&lt;br /&gt;
 &lt;br /&gt;
 for(int i = 0 ; i &amp;amp;lt; 10 ; ++i)&lt;br /&gt;
 	v.push_back(new Object); // new로 넣어줬다.&lt;br /&gt;
 &lt;br /&gt;
 ...&lt;br /&gt;
 ...&lt;br /&gt;
 &lt;br /&gt;
 for(vector&amp;amp;lt;Object*&amp;amp;gt;::iterator i = v.begin() ; i != v.end() ; ++i)&lt;br /&gt;
 	delete *i // 지워주자.&lt;br /&gt;
 &lt;br /&gt;
 return 0;&lt;br /&gt;
&lt;br /&gt;
* 하지만 ... 부분에서 예외가 터져서 프로그램이 끝나버린다면? 또다시 Detected Memory Leaks!&lt;br /&gt;
&lt;br /&gt;
== 보완법 1(class for function object) == &lt;br /&gt;
* 이를 보완하기 위해 delete를 함수 객체로 만드는 법이 있다.(뭐야 이거?)&lt;br /&gt;
** Fucntion Object 보통 class키워드를 쓰던데, struct(이하 class라고 씀)를 써놨군. 뭐, 별 상관없지만, 내부 인자 없이 함수만으로 구성된 class이다. STL에서 Generic 을 구현하기에 주효한 방법이고, 함수로만 구성되어 있어서, 컴파일시에 전부 inline시킬수 있기 때문에 최적화 문제를 해결했음. 오 부지런히 보는가 보네. 나의 경쟁심을 자극 시키는 ^^;; --[[상민]]&lt;br /&gt;
 struct DeleteObject : public unary_function&amp;amp;lt;const T*, void&amp;amp;gt;&lt;br /&gt;
 {&lt;br /&gt;
          template&amp;amp;lt;typename T&amp;amp;gt;&lt;br /&gt;
 	void operator()(const T* ptr) const&lt;br /&gt;
 	{&lt;br /&gt;
 		delete PTR;&lt;br /&gt;
 	}&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 void f()&lt;br /&gt;
 {&lt;br /&gt;
 	...&lt;br /&gt;
 	for_each(v.begin(), v.End(), DeleteObject());    // 정말 이상하군..--;&lt;br /&gt;
 }&lt;br /&gt;
* 밑에꺼 쓰고 덧붙이는 건데 이 방법은 열라 안좋은 거란다.(struct DeleteObject, 쳇 그러면서 뭐하러 설명해?-.-)&lt;br /&gt;
&lt;br /&gt;
== 보완법 2(Smart Pointer) == &lt;br /&gt;
* 또 다른 방법으로 컨테이너에 포인터를 넣는 대신 스마트 포인터를 넣는 것이다.(아악..--; MDC++(MEC++)을 봐야 하는가..ㅠ.ㅠ)&lt;br /&gt;
 typedef boost::shared_ptr&amp;amp;lt;Object&amp;amp;gt; SPO;	// boost 라이브러리라는게 있단다.&lt;br /&gt;
 &lt;br /&gt;
 vector&amp;amp;lt;SPO&amp;amp;gt; v;&lt;br /&gt;
 for(int i = 0 ; i &amp;amp;lt; 10 ; ++i)&lt;br /&gt;
 	v.push_back(SPO(new Object));&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Item8. Never create containers of auto_ptrs. =&lt;br /&gt;
* 생략. 도무지 뭔말하는건지 모르겠다. COAP는 또 뭐고..--;&lt;br /&gt;
** 컨테이너를 오토 포인터로 생성하지 말것~&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
= Item9. Choose carefully among erasing options. =&lt;br /&gt;
== 어떤 컨테이너가 int값들을 담고 있다고 하자. 거기서 1982 라는 숫자를 몽땅 지워주고 싶다면? ==&lt;br /&gt;
* Contiguous-memory container 일때&lt;br /&gt;
 c.erase( remove(c.begin(), c.end(), 1982), c.end() );        // 이건 내부적으로 어떻게 돌아가는 걸까. 찾아봐야겠군. &lt;br /&gt;
* list일때 - erase 써도 되지만 remove가 더 효율적이다.&lt;br /&gt;
 c.remove(1982);&lt;br /&gt;
* Associative container 일때 - remove쓰면 난리난다.(없으니깐--;) 또 제네릭 알고리즘 remove도 역시 안된다. 컨테이너가 망가질수도 있다.&lt;br /&gt;
 c.erase(1982);&lt;br /&gt;
 &lt;br /&gt;
== 조건 검사해서 몽땅 지워주기 ==&lt;br /&gt;
* 또 이상한 팁이 있군. bool형을 리턴하는 함수를 인자로 같이 넣어주면 그 조건을 만족하는 값은 모조리 지워주는..(함수 포인터일까.. 함수 포인터는 아직도 언제 쓰는건지 모르겠다. 혹시 아시는분은 좀 가르쳐 주세요^^;)&lt;br /&gt;
** 함수포인터임. (또는 위에서의 함수객체.) 해당 함수 객체로 조건을 파악한뒤 삭제하거나 비교,소트 하는 일을 많이 함. --&amp;amp;#91;1002&amp;amp;#93;&lt;br /&gt;
 &lt;br /&gt;
=== 쉽게 할수 있는 컨테이너들 ===&lt;br /&gt;
 bool badValue(int x) { ... }    // 넣어줄 함수 선언&lt;br /&gt;
&lt;br /&gt;
 c.erase( remove_if(c.begin(), c.end(), badValue), c.end() );    // Contiguous-memory Container일때(vector, deque, string)&lt;br /&gt;
&lt;br /&gt;
 c.remove_if(badValue);    // list일때&lt;br /&gt;
&lt;br /&gt;
=== Associative Container 일때 ===&lt;br /&gt;
* 쉽지만 비효율적인 방법 - remove_copy_if 를 사용한다. 이것은 지우고 싶은걸 제외한 나머지 것들을 새로운 컨테이너로 옮긴다. 그 다음에 원래 컨테이너를 새로 만든것과 바꿔 버린다.(우울하군--;)&lt;br /&gt;
 AssocContainer&amp;amp;lt;int&amp;amp;gt; c;    // map,multimap,set,multiset 등을 일반화한 이름이다. 실제로 저런 이름의 컨테이너는 없다.--;&lt;br /&gt;
 ...&lt;br /&gt;
 AssocContainer&amp;amp;lt;int&amp;amp;gt; goodValues;&lt;br /&gt;
 &lt;br /&gt;
 remove_copy_if(c.begin(), c.end(), inserter(goodValues, goodValues.end()), badValue);     // 헉 이분법--;. 보면서 느끼는 거지만 정말 신기한거 많다. 저런 것들을 도대체 무슨 생각으로 구현했을지..&lt;br /&gt;
 &lt;br /&gt;
 c.swap(goodValues);       // c랑 goodValues랑 바꾼다. 이런것도 있군.&lt;br /&gt;
* 어렵지만 효율적인 방법 - 뭐 또 파일에 쓴다고 해서 이상한방법 쓰는데 그냥 넘겼다.&lt;br /&gt;
 AssocContainer&amp;amp;lt;int&amp;amp;gt; c;&lt;br /&gt;
 &lt;br /&gt;
 for(AssocContainer&amp;amp;lt;int&amp;amp;gt;::iterator i = c.begin() ; c != c.end() ; )&lt;br /&gt;
 {&lt;br /&gt;
     if(badValue(*i))&lt;br /&gt;
     {&lt;br /&gt;
         c.erase(i++);     // 지워야 할 값이면 일단 지우고 반복자 하나 증가시켜준다. 후위 연산자는 그 값을 미리 복사를 하기 &amp;amp;amp;#46468;문에 가능한 일이다. &lt;br /&gt;
     }                     // 그냥 지우면 그 반복자는 void가 된다. 안좋다--;&lt;br /&gt;
     else ++i;             // 아니면 그냥 증가&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== 잡담 ==&lt;br /&gt;
* 반복자를 이용해서 루프를 돌다가 어떤 걸 지우면, 그걸 가리키고 있던 반복자는 갱신된다. 다음에 어떻게 될지 장담 못한다는 뜻이다. 주의하자.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
= Item10. Be aware of allocator conventions and restrictions. =&lt;br /&gt;
----&lt;br /&gt;
= Item11. Understand the legitimte uses of custom allocators. =&lt;br /&gt;
----&lt;br /&gt;
= Item12. Have realistic expectations about the thread safety of STL containers. =&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[EffectiveSTL]]&lt;br /&gt;
&lt;/div&gt;</summary>
		<author><name>imported&gt;Unknown</name></author>
	</entry>
</feed>