[STL] 벡터 vector
Updated:
vector
는 컨테이너형 자료구조이며 STL을 사용하여 동적 배열 구조를 구현한 것으로 크기가 가변적으로 변하는 배열이라고 할 수 있습니다. vector를 활용하여 배열에 비해 메모리를 효율적으로 사용할 수 있고 동적으로 값을 원하는 위치에 추가하거나 삭제할 수 있으며 vector의 capacity가 가득 찼을 경우 자동으로 capacity의 크기가 두배로 늘려 준다는 장점 등이 있습니다.
vector의 구조
[STL] 벡터의 멤버함수 및 사용
#include<vector>
vector<int> v;
- assign$($) : 두번째 인자값으로 첫번째 인자로 전달되는 수 만큼의 원소를 할당
- push_back$($) : 벡터의 맨 마지막 원소 뒤에 값을 삽입
- pop_back$($) : 벡터의 맨 마지막 원소를 삭제
- insert$($) : 첫번째 인자인 iterator가 가리키는 위치에 두번째 인자 값 삽입. 삽입 위치의 뒤에 있던 원소들의 인덱스는 한칸씩 뒤로 밀림.
- erase$($) : 특정 위치의 원소나 지정 범위의 원소를 삭제
- clear$($) : 벡터의 모든 원소를 삭제
- begin$($) : 벡터의 첫번째 원소의 랜덤 접근 반복자를 반환
- end$($) : 벡터의 마지막 원소 다음의 반복자를 반환
- rbegin$($) : 역방향으로 첫번째 원소의 반복자를 반환
- rend$($) : 역방향으로 마지막 원소의 반복자를 반환
- size$($) : 벡터의 총 원소수를 반환
- capacity$($) : 벡터에 할당되어있는 배열의 크기를 반환
- empty$($) : 벡터가 비었으면 true반환 아니면 false반환
- resize$($) : 벡터의 크기를 첫번째 인자값으로 변경한다.
- reserve$($) : n개의 원소를 가진 벡터를 동적할당 시킵니다.
- v2.swap$($v1) : v1과 v2의 원소와 capacity를 스왑한다.
사용 예제
#include<iostream>
#include<vector>
using namespace std;
int main(void)
{
vector<int> v1(5); //capacity가 5인 배열을 동적 할당
vector<int> v2(6,2); //capacity가 6이고 2로 초기화된 배열을 동적 할당
vector<int>::iterator iter;
cout<<"v2에 할당된 배열의 크기는 : "<<v2.capacity()<<'\n'; // capacity=6
v2.push_back(1); // v2[2 2 2 2 2 2 1]
cout<<"v2가 full 상태에서 원소 삽입하면 배열의 크기는 두배가된다 : "<<v2.capacity()<<'\n'; //capacity=12
cout<<"v2의 6번째 원소 값 : "<<v2[6]<<'\n'; // 1
v2[0]=9;
cout<<"iterator를 사용한 v2 전체 원소 접근 : ";
for(iter = v2.begin(); iter != v2.end() ; iter++) cout << *iter << " "; // 9 2 2 2 2 2 1
iter=v2.begin()+1; // iterator는 v2의 두번째 원소를 가리키고 있다
cout<<'\n';
v2.insert(iter,8); //v2의 index[1]에 8추가하고 나머지 원소는 뒤로 밀어낸다
for(int i=0; i<v2.size(); i++) cout<<v2[i]<<" "; // 9 8 2 2 2 2 2 1
cout<<'\n';
v2.erase(iter+1, v2.end()-1); // v2에서 3번째~7번째 원소를 삭제
for(int i=0; i<v2.size(); i++) cout<<v2[i]<<" "; // 9 8 1
cout<<"\nv1과 v2를 SWAP! v2는 : ";
v2.swap(v1);
for(int i=0; i<v2.size(); i++) cout<<v2[i]<<" "; // 0 0 0 0 0
return 0;
}
결과
v2에 할당된 배열의 크기는 : 6
v2가 full 상태에서 원소 삽입하면 배열의 크기는 두배가된다 : 12
v2의 6번째 원소 값 : 1
iterator를 사용한 v2 전체 원소 접근 : 9 2 2 2 2 2 1
9 8 2 2 2 2 2 1
9 8 1
v1과 v2를 SWAP! v2는 : 0 0 0 0 0
vector를 리턴 값으로 받는 경우
vector등의 STL 데이터 타입을 함수에서 데이터로 받는 경우를 생각해보겠습니다.
#include<iostream>
#include<vector>
using namespace std;
vector<int> func()
{
vector<int> data;
data.push_back(10);
data.push_back(20);
data.push_back(30);
return data;
}
int main(int argc, char* argv[])
{
vector<int> my_data=func();
for(int i=0; i<my_data.size(); i++) cout<<my_data[i]<<' '; // my_data [10 20 30]
return 0;
}
위와 같은 경우에서 과연 my_data에 값을 제대로 받을 수 있을지 고민될 수 있습니다. 결론 부터 말하자면 call by reference 형태로 func$($)의 data의 값들이 my_data에 효율적으로 전달됩니다. 이는 STL의 특성 덕분이고 다른 경우엔 위험한 오류를 범하게 될 가능성이 있습니다.
위의 프로그램의 실행 순서를 보면, 먼저 메인 함수에서 벡터 my_data 포인터가 생성되고 func$($) 함수가 수행되면서 벡터 data 배열이 동적 할당됩니다. 이때 my_data 포인터는 return data; 를 통해 func() 함수에 의해서 생성된 data 배열을 가리키게 되지만 func() 함수가 return에 의해 종료됨과 동시에 동적 할당된 data 배열 또한 해제되어 버리기 때문에 결국 my_data 포인터는 엉뚱한 값을 가리키게 되는 것 입니다.
반면 STL의 경우 동적 할당된 data 배열을 복제 연산하여 return 하기 때문에 my_data가 복제된 data 배열을 가리키고 func()함수가 종료되어 data 배열이 해제되더라도 값을 잘 전달 받을 수 있었던 것입니다.
Leave a comment