본문 바로가기
C++ STL

[C++ STL] vector

by Junk_Seo 2018. 3. 18.
반응형

vector

연속된 메모리 기반의 컨테이너(배열 기반의 컨테이너)이다. 따라서 메모리를 먼저 잡아놓고 사용해야 한다.

그렇지 않으면 데이터를 추가할 때마다 메모리 재편성 작업을 한다. (vector는 메모리를 2중으로 관리하고 있다.(전체 길이와 데이터 개수)

vector 메모리 재편성

STL 컨테이너는 데이터 삽입 시 메모리의 크기가 부족한 경우 메모리를 2의 증가율만큼 크기를 늘리도록 구현하고 있다.

재할당을 할 때 컨테이너가 원래 가지고 있었던 메모리에 저장된 모든 요소 데이터를  새 메모리에 복사하고 원래의 메모리에 저장된 모든 객체를 소멸시키고 원래 메모리를 해제한다.

(할당 - 복사 - 소멸 - 해제의 비용이 들어간다.)

다음을 보면 메모리 재편성을 어떻게 하고 있는지 알 수 있다.

위 코드를 보면 int형 데이터를 저장하는 vector를 사용하고 있는데, 메모리의 size를 잡지 않고 데이터를 추가하고 있다.

출력을 보면 데이터가 추가되는 것에 따라 vector의 용량이 증가하여 메모리 재편성을 하고 있는 것을 볼 수 있다. 

-capacity() : vector의 전체 길이를 출력한다. (데이터의 개수와는 다르다.)

-size()       : vector에 추가된 데이터의 개수를 출력한다.

vector는 "전체 길이에서 얼마 만큼 사용하고 있는가" 중요하다.
메모리를 2중으로 관리하고 있으므로 전체길이와 데이터 개수를 따로 관리한다.
전체 길이를 할당했다고 해서 데이터가 할당된 것은 아니다. 이 때 데이터를 추가하면 할당된 전체길이에 데이터가 할당된다.
vector를 사용하는데 전체 길이를 설정하지 않고 사용하면 데이터를 추가할 때 마다 메모리 재편성 작업을 하여 오버헤드가 증가한다.

 

reserve() 함수

reserve() 인터페이스가 vector의 전체길이를 할당하는 작업을 한다. 
vector의 인터페이스 reserve()는 전체 길이는 잡고 사용개수는 0으로 시작한다.
즉 사용자가 데이터를 추가할 때 마다 사용개수가 변한다.
(데이터를 전체길이보다 많이 추가하면 메모리 재편성 작업을 한다.)

 

위 코드를 보면 vector의 size를 9로 설정하고 10개의 데이터를 추가하고 있다. 

9개의 데이터를 추가할 때까지는 메모지 재편성 작업을 하지 않지만 vector의 용량을 넘어선 10번째 데이터를 추가하자 메모리 재편성 작업을 한 것을 알 수 있다.

resize() 함수

reserve() 없이 resize()를 사용하면 resize()한 길이만큼 전체 길이를 설정하고 초기값으로 데이터를 전체길이의 개수만큼 데이터를 생성한다.

vector의 인터페이스 resize()로 전체길이를 잡으면 사용개수도 전체길이가 된다.

즉, 사용자가 데이터를 추가하지 않았지만 사용개수가 전체길이로 잡혀있다. 따라서 이때 데이터를 추가하면 전체길이가 증가하여 메모리 재편성 작업을 한다.

reserve() 다음에 resize()를 하는데 전체길이보다 작거나 같게 resize()를 하면 전체길이에서 resize() 한 만큼 초기값으로 데이터를 설정한다. 

resize()를 전체길이보다 길게 하면 메모리 재편성을 하고 데이터를 초기값으로 설정한다.

resize()를 사용하면 데이터를 추가할 때마다 메모리 재편성을 하므로 배열처럼 vector를 index를 사용하여 데이터를 삽입한다.

(vector를 배열처럼 사용할 거라면 차라리 배열을 사용한다.)

 

<예제 1>

위 코드를 보면 resize() 함수를 통해 vector의 전체 용량을 9로 잡고 9개의 데이터를 초기값으로 설정했다. 

(vector의 전체길이와 데이터 개 : 9개)

그 이후에 데이터 1개를 추가하자 vector의 전체 용량을 넘어섰기 때문에 메모리 재편성 작업을 하고 vector의 마지막에 데이터가 추가되었다.

 

<예제 2>

resize() 함수를 통해 vector의 전체 용량을 9로 설정하고 9개의 데이터를 초기값으로 설정하였다.

그리고 []를 통해 배열처럼 vector에 접근하여 데이터를 세팅하고 있다.

 

<예제 3>

vector의 전체길이를 reserve() 함수를 통해 9로 설정하고 다시 resize() 함수를 통해 전체길이보다 긴 길이로 설정하였다. 

이로 인해 메모리 재편성 작업을 하고 vector의 데이터를 초기값으로 설정하였다.

그리고 [] 를 통해 배열처럼 데이터를 세팅하고 있다.

생성자를 통한 길이 설정

vector를 사용하는데 생성자를 이용해서 메모리를 잡으면(길이를 잡으면) 그 개수만큼 데이터를 잡아버린다.

즉, 생성자를 통해 10의 전체길이를 주면 10의 전체 길이를 잡고 초기값으로 10개의 데이터를 생성한다는 소리다. 이때 push_back()으로 데이터를 추가하면 11번째 데이터가 생성된다.(전체 길이를 넘어가므로 메모리 재편성 작업을 한다.)

생성자를 사용하면 reserve()와 resize()를 같은 수로 설정한 것과 같다. 즉, vector를 배열처럼 사용하는데, 이럴 거면 배열을 사용하다. 

그리고 생성자로 일을 하면 무슨 일을 하는지 잘 모르므로 생성자로 일을 하지 말자.

vector의 생성자를 통해 전체길이를 10으로 설정하고 10개의 데이터를 초기값으로 설정하고 있다.

그다음에 데이터를 추가하자 11번째 데이터가 추가되어 메모리 재편성 작업을 하고 있다.

vector 장점

검색이 링크드리스트보다 빠르다.(상수 시간에 검색 가능)

데이터의 길이가 정해저 있는 상태에서 특정 데이터에 접근하고자 하는 경우에 사용.

vector 단점

배열기반이기 때문에 중간 데이터를 삭제하는데 오버헤드 증가

중간 데이터 삭제가 빈번하게 일어나는 경우 사용하지 않는다.

데이터와 index를 연결하여 사용하는 경우 중간데이터를 삭제하면 index와 데이터가 어긋난다.

결론

연속된 메모리 기반의 컨테이너인 vector를 사용하려면 reserve()를 통해 전체 길이를 설정하여 사용해야 메모리 재편성을 피할 수 있습니다.

vector를 사용할 때 전체길이가 계속해서 바뀌는 것은 잘못된 사용법이다. 따라서 vector는 사용하기 전에 전체 길이를 잡아 놓고 사용해야 한다. 그리고 전체길이를 넘기지 않도록 해야 한다.

 

 

 

참고 : https://blog.naver.com/dx1122/70179736144

 

 

 

반응형

'C++ STL' 카테고리의 다른 글

[C++ STL] map, iterator를 통한 데이터 추가  (0) 2018.03.18