일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Vector
- 게임
- 반복자
- 다형성
- implicit conversion
- c++
- 티스토리챌린지
- 비교 함수 객체
- UE4
- operator new
- resource management class
- 참조자
- 예외
- Smart Pointer
- Effective c++
- 오블완
- 언리얼
- 스마트 포인터
- 암시적 변환
- virtual function
- 영화 리뷰
- reference
- more effective c++
- 루아
- 상속
- 메타테이블
- 영화
- exception
- lua
- effective stl
Archives
- Today
- Total
스토리텔링 개발자
[Effective STL] 30. 알고리즘 사용 시 목적지 범위(destination range) 주의 본문
728x90
항목 30. 알고리즘의 데이터 기록 범위(destination range)는 충분히 크게 잡자
컨테이너 요소 삽입 시
int transmogrify(int x); // 정수 x를 받아 어떤 새로운 값을 만드는 함수
vector<int> values;
... // values에 데이터를 넣는다.
// values 요소들에 transmogrify를 적용하고 result에 삽입한다.
// 하지만, 버그가 있다.
vector<int> results;
transform(values.begin(), values.end(), results.end(), transmogrify);
- transform 결과 기록 순서
- values[0]을 매개변수로 가져온다.
- transmogrify를 호출하여 값을 변환한다.
- *results.end()에 대입한다.
- values[1]에 대해 1번부터 다시 진행
- 허나, 이 시점에서 results에는 공간이 할당되어 있지 않다.
- 즉, 목적지 범위인 results.end()에는 아무런 객체가 없다.
- 알고리즘이 알아서 컨테이너에 insert하며, 컨테이너가 공간을 할당할 것이라 기대했지만..
- 그렇게 하려면 STL에게 똑바로 알려줘야 한다.
vector<int> results;
transform(values.begin(), values.end(), back_inserter(results), transmogrify);
// 이 경우, back_inserter는 push_back을 호출하게 되어 있으므로,
// 대상 컨테이너는 반드시 push_back을 지원해야 한다.
results 앞에다가 transform 결과를 추가하고 싶다면?
- 물론 그냥 front_inserter를 사용할 수 있지만..
- 객체들을 순서대로 각각 push_front 시키므로 순서가 반대로 삽입된다.
- vector는 push_front를 지원하지 않는다.
- values를 뒤집어서 넣어주면 된다.
list<int> results;
transform(values.rbegin(), values.rend(), front_inserter(results), transmogrify);
임의의 위치를 지정하여 결과를 추가하고 싶다면?
- 반복자 어댑터를 사용하면 된다.(항목 5 참조)
vector<int> results;
... // 데이터가 몇 개 들어있다.
transform(values.begin(), values.end(),
inserter(results, results.begin() + results.size() / 2), // 중간에 삽입
transmogrify);
오버헤드 줄이기
- 이 모든 inserter들은 한번에 한 개의 요소만 삽입하는데, 이는 오버헤드이다.(항목 5 참조)
- 하지만, transform은 어쨌든 한 번에 하나의 값을 목적지 범위에 저장하기에 바꿀 수 있는 방법은 없다.
- 대상 컨테이너가 vector, string이라면 reserve를 호출하여 오버헤드를 최소화할 수 있다.(항목 14 참조)
vector<int> values;
vector<int> results;
...
reuslts.reserve(results.size() + values.size()); // 공간 확보
transform(values.begin(), values.end(),
inserter(results. results.begin() + results.size() / 2),
transmogrify);
- reserve는 컨테이너의 요소 크기가 아니라 용량(capacity)만을 증가시킨다는 사실을 기억할 것.
- 그러므로 reserve를 호출한 후에도 반복자 어댑터를 사용해야 한다.
vector<int> values;
vector<int> results;
...
results.reserve(results.size() + values.size());
// transform(values.begin(), values.end(), results.end(), transmogrify);
// reserve를 했더라도 위 코드는 미정의 동작!!
// 아래처럼 해야 한다.
transform(values.begin(), values.end(), back_inserter(results), transmogrify);
새 요소가 아니라 원래의 요소를 덮어쓰고 싶은 경우?
- 방법 1 : resize로 크기를 확보한다.
vector<int> values;
vector<int> results;
...
if(results.size() < values.size())
{
// results의 크기를 values의 크기만큼으로 맞춘다.
results.resize(values.size());
}
// values를 results에 덮어쓴다.
transform(values.begin(), values.end(), results.begin(), transfmogrify);
- 방법 2 : results를 clear한 후 반복자 어댑터를 사용한다.
...
results.clear(); // 요소 모두 삭제
results.reserve(values.size());
transform(values.begin(), values.end(), back_inserter(results), transmogrify);
728x90
'개발 > Effective STL' 카테고리의 다른 글
[Effective STL] 32. remove-erase 관용구 (0) | 2024.12.19 |
---|---|
[Effective STL] 31. 상황별 정렬 선택하기 (0) | 2024.12.18 |
[Effective STL] 29. istream_iterator vs istreambuf_iterator (0) | 2024.12.16 |
[Effective STL] 28. 반복자 base() 유의점 (0) | 2024.12.13 |
[Effective STL] 27. const_iterator를 iterator로 바꾸기 (0) | 2024.12.12 |
Comments