C++ Vector reserve( )와 resize( )의 차이
둘의 차이는 한마디로 end( )의 위치가 다르다. resize( )를 하게 되면 그만큼의 생성자(constructor)가 실행된다. 이 개념이 왜 중요하냐면, size와 capacity 때문이다. 간단히 설명하자면 메모리에 이미 할당되어 있는 vector의 크기가 capacity이고 이 안에 원소의 수가 size이다. size가 capacity를 넘어가려고 하면 메모리의 더 큰 공간에 새로운 capacity를 만들고 vector를 이동하는 식으로 구현이 되어 있다.
맨처음 예시처럼 vector를 선언만 하는 경우 begin( )과 end( )가 같고 size와 capacity는 모두 0이다.
만약에 이 vector를 resize(5)하게 되면 size는 5, capacity도 이에 맞춰 5가 된다. 하지만 reserve(5)를 하면 size는 0, capacity는 5가 된다.
이처럼 각각 end( )의 위치가 다르기 때문에 push_back( ) 했을 때의 동작이 다르다.
C++ Vector resize() 후 push_back()
resize를 한 vector에 push_back을 하게 되면 이미 size가 capacity가 같은 상태이다. 그래서 capacity를 늘려주고 새로운 원소를 end( ) 앞에 추가해준다.
C++ Vector reserve( ) 후 push_back( )
reserve를 한 vector에 push_back을 하게 되면 size가 0이었기 때문에 vector의 begin( ) 에 추가한다.
해설
vector는 new의 wrapper이기 때문에 new의 사용법으로 생각하면 알기 쉽다. resize든 reserve든 그만큼의 메모리를 확보하는 것에는 변함이 없다.
- 이럴때는 reserve를 사용한다.
push_back 했을 때 '사용이 끝난 요소의 다음 요소'에 값이 들어간다.
리스트의 끝에 추가해 나가는 듯한 느낌이 든다.
size( )를 보면 저장한 항목의 개수를 알 수 있다.
적어도 reserve에서 지정한 횟수만큼의 push_back에 관해서는, 재할당이 발생하지 않는 것이 보장된다. - 이럴때는 resize를 사용한다.
size( )가 확보한 요소 수이므로, 일반 배열과 동일하게 사용할 수 있다. - 여담
동작의 차이로 인해 resize 한 후에 push_back 하는 일은 드물다.
또한 반대로 reserve 후 size( ) 이상의 요소에 대해 operator [ ]로 접근해서는 안 된다.
이러한 일을 하고 있는 코드는 버그일 가능성이 있다 (특히 후자의 경우)
실험
아래 코드의 결과를 예상해보자.
std::vector<char> v;
v.reserve(100*100);
printf("100*100 size:%d capacity %d\n",v.size(),v.capacity() );
v.resize(30*30);
printf("30*30 size:%d capacity %d\n",v.size(),v.capacity() );
v.resize(50*50);
printf("50*50 size:%d capacity %d\n",v.size(),v.capacity() );
v.resize(200*200);
printf("200*200 size:%d capacity %d\n",v.size(),v.capacity() );
100*100 size: 0 capacity 10000
30*30 size: 900 capacity 10000
50*50 size: 2500 capacity 10000
200*200 size: 40000 capacity 40000
vector를 초기화하면서 어느 정도 크기로 reserve를 하여 capacity를 넓혀두면 나중에 resize시 메모리 재할당 가능성이 줄어들고 빠르게 처리할 수 있다.
그리고 resize를 사용하면 그 갯수만큼의 생성자가 실행되어 성능에 영향을 줄 수도 있다.
#include <vector>
#include <stdio.h>
class CC{
public:
CC(){
printf("construct...\n");
}
};
int main(int argc, char* argv[])
{
std::vector<CC> v;
v.reserve(100);
v.resize(5);
printf("v.size() : %d", v.size());
getchar();
return 0;
}
/* 결과값
construct...
construct...
construct...
construct...
construct...
5
*/
'C | C++' 카테고리의 다른 글
C++ unique_ptr 스마트 포인터에 대한 매우 자세한 설명 (0) | 2022.09.30 |
---|---|
auto 키워드 (1) | 2022.09.10 |
Rvalue reference 정리한 내용 (0) | 2020.11.20 |
const 와 readonly 의 차이 (0) | 2020.05.22 |
c++ 구조2 (0) | 2019.10.03 |