vector와 string에 있어서의 메모리 증가는 재할당이란 과정을 거쳐서 이루어 진다.(현재 사이즈의 증가가 아닌 컨테이너에서 할당해놓은 메모리가 부족해 질때)
- 컨테이너의 현재 용량의 몇배가 되는 메모리 블록을 새로 할당 (일반적으로 2배)
- 컨테이너가 가지고 있었던 메모리에 저장된 모든 요소 데이타(객체)를 새 메모리에 복사
- 원래 메모리에 저장된 모든 객체를 소멸
- 원래의 메모리를 해제
라는 과정을 거친다.
이런 오버헤드를 줄이기 위해서 필요한 만큼의 메모리를 미리할당하고 데이타를 삽입한뒤 관리하는 방식을 사용할수 있다. 이때 사용하는것이
reserve 이다.
예를 들어
vector<int> v;
for(int i=0; i<1000; i++) v.push_back(i);
라는 코드는 루프를 도는 동안 대략 10번 정도의 메모리 재할당이 일어나게 된다.(메모리크기를 2배씩 잡을때) 하지만
reserve를 사용하면 이런 불필요한 메모리 재할당을 막을수 있다.
vector<int> v;
v.reserve(1000);
for( int i=0; i<1000; i++ ) v.push_back(i);
위의 코드는 루프를 도는 동안 메모리 할당이 한번도 일어나지 않게 된다.
그리고
size와 capacity의 관계를 잘 생각해보면 요소 삽입시 vector나 string에서 재할당이 일어나는 시기를 예측할수 있다.
string s;
…
if( s.size() < s.capacity() ) s.push_back(‘X’);
정리하면 reserve를 이용해서 불필요한 메모리 재할당을 피하는 방법은 두가지 정도 이다.
- 컨테이너에 저장될 요소의 개수를 미리 파악해서 정확한 reserve 호출
- 컨테이너에 저장될 최대 요소의 개수를 할당하고 요소 삽입후 남는 메모리를 삭제 (EffectiveSTL17 을 참고)
참고
- size() : 현재 컨테이너에 들어있는 요소의 개수
- capacity() : 현재 컨테이너에 재할당없이 추가할수 있는 요소의 개수
- resize(size_t n) : 컨테이너의 요소의 개수를 n으로 변경. 만약 현재 컨테이너의 개수가 n보다 크다면 n이후의 요소들은 삭제, 크다면 n크기로 재할당하고 뒤에 남는 공간은 요소 객체의 기본생성자로 생성해 채워 놓는다.
- reserve(size_t n) : 컨테이너의 용량을 최소 n으로 맞춘다. 현재의 capacity()가 더 작다면 n의 크기로 재할당을 하며, 크다면 아무것도 하지 않는다. (이미 할당된 메모리의 공간을 줄이는 일이 일어날수도 있지만 삽입된 데이타를 줄이는 일은 없다.)
|