[펌] Effective STL 읽은 후 정리~
#################
컨테이너 종류
#################
표준 STL 시퀀스 컨테이너 : vector, string, deque, list
표준 STL 연관 컨테이너 : set, multiset, map, multimap
비표준 시퀀스 컨테이너 : slit, rope
비표준 연관 컨테이너 : hash_set, hash_multiset, hash_map, hash_multimap
string 대한 vector<char>
표준 연관 컨테이너 대신 사용 되는 vector
STL에 속하지 않는 표준 컨테이너 : 배열, bitset, valarray, stack, queue, priority_queue
-------------------------
연속 메모리 컨테이너
-------------------------
삽입 삭제시 메모리가 밀려 지거나 땡겨 지는 컨테이너(무효화!!! <-- 특히 이넘을 조심 해야 함.)
vector, string, deque.
---------------------
노드 기반 컨테이너
---------------------
삽입 삭제시 메모리 포인터만 영향을 받음. 밀리는 현상 없음.
list, slist, set, multiset, map, multimap,
hash_set, hash_multiset, hash_map, hash_multimap
#######################################
STL은 복사에서 시작 하고 복사로 끝난다.
#######################################
값을 얻거나 넣거나 할때 모두 복사로 이루어 집니다.
상속된 클래스를 사용할 경우 베이스 클래스로 형 지정 했다면,
복사라는 특징 때문에 상속된 클래스는 잘리게 됩니다.(slicing problem)
이에 대한 해결 책은 클래스 포인터를 사용 하는 것입니다.(추후 설명)
배열
T w[maxT];
사이즈 0
vector<T> vw;
max T 만큼 미리 확보
vector<T> vw;
vw.reserve(maxT);
######################################
size() == 0을 쓰지 말고 empty()를 써라
######################################
size()를 제공 하지 않는 것도 있다. 예 list
######################################
단일 요소 반복 대신 범위 함수를 쓰자
######################################
void container::assign(시작, 끝)
void container::contrainer(시작, 끝)
void container::insert(삽입위치, 삽입 시작, 끝)
iterator container::erase(시작, 끝) - 시퀀스 컨테이너
void container::erase(시작, 끝) - 연관 컨테이너(반복자의 반환으로 성능 저하 되므로...)
#####################
C++의 어이 없는 동작
#####################
#include <iostream>
class T {
public:
T() { cout << "ok" << endl;}
};
int main() {
T t1(); // 함수 선언, nothing...
T t2; // t 객체 생성, out "ok"
}
같은 원리로...
ifstream dataFile("ints.dat");
list<int> data(istream_iterator<int>(dataFile), istream iterator<int>()); // 단순한 함수 선언에 불과 하다.
list<int> data((istream_iterator<int>(dataFile)), istream iterator<int>()); // 해결, 범용성 떨어짐
<해결>
ifstream dataFile("ints.dat");
istream_iterator<int> dataBegin(dataFile);
istream_iterator<int> dataEnd;
list<int> data(dataBegin, dataEnd);
############################################################################
new로 생성한 포인터 컨테이너는 컨테이너가 소멸 되기 전에 포인터를 delete하자
############################################################################
vector<Widget *> vwp;
for(int i=0; i<NUM; ++i) {
vwp.push_back(new Widget); // new로 생성
}
//... 사용
for(vectro<Widget *>::iterator i = vwp.begin(); i!=vwp.end(); ++i)
delete *i; // delete로 소멸
<문제>
1. for루프는 for_each보다 명확하지 못하다.
2. 사용 중에 vwp가 예외를 던진 다음 메모리 누수 문제는 여전히 남는다.
<1번 해결>
struct Delete Object {
template<typename T>
void operator()(const T*ptr) const {
delete ptr;
}
};
for_each(vwp.begin(), vwp.end(), DeleteObject());
<2번 해결>
www.boost.org의 스마트 포인터 라이브러리를 사용 합니다.
void doSomething()
{
typedef boost::shared_ptr<Widget> SPW;
vector<SPW> vwp;
for(int i=0; i<NUM; ++i)
vwp.push)back(SPW(new Widget));
...
}
doSomething()함수가 끝나더라도, 예외가 발생 해도 메모리가 새지 않습니다.
##############################
auto_ptr 은 절대로 쓰지 말아라
##############################
auto_ptr은 스마트 포인터가 아니다. 자세한것은 Effective STL 참조!!!
##################
삭제의 조심 스러움
##################
무효화된 i에 대하여 ++i를 하고 있다.
AssocContainer<int> c; // AssocContainer는 연관 컨테이너.
...
for(AssocContainer<int>::iterator i=c.begin(); i!=c.end(); ++i) {
if(badValue(*i)) c.erase(i);
}
<해결>
AssocContainer<int> c;
...
for(AssocContainer<int>::iterator i=c.begin(); i!=c.end(); ) {
if(badValue(*i)) c.erase(i++);
else ++i;
}
연속 컨테이너인 경우 i++시 전체가 무효화 됩니다.
<해결>
for(SeqContainer<int>::iterator i=c.begin(); i!=c.end();) {
if(badValue(*i)) {
i = c.erase(i);
}
else ++i;
}
######################################################
STL 쓰레드는 쓰레드에 안전하지 않다.(직접 관리 해야함)
출처 : http://blog.naver.com/jinowin/6000269089
[출처] Effective STL 읽은 후 정리~|작성자 지노윈
'Programming > STL' 카테고리의 다른 글
유틸 클래스 pair (0) | 2011.04.08 |
---|---|
2.1 문자열을 키로 쓰는 map, set 성능 향상시키기 (0) | 2011.02.07 |
항목 27 : const_iterator를 iterator로 바꾸는 데에는 distance와 advance를 사용하자. (0) | 2010.11.03 |
부스트(boost) 관련 스프링노트 (0) | 2010.06.11 |
C++ STL int -> string, string -> int 로 변환하기 (1) | 2010.04.27 |