[STL] 벡터 vector

Updated:

vector는 컨테이너형 자료구조이며 STL을 사용하여 동적 배열 구조를 구현한 것으로 크기가 가변적으로 변하는 배열이라고 할 수 있습니다. vector를 활용하여 배열에 비해 메모리를 효율적으로 사용할 수 있고 동적으로 값을 원하는 위치에 추가하거나 삭제할 수 있으며 vector의 capacity가 가득 찼을 경우 자동으로 capacity의 크기가 두배로 늘려 준다는 장점 등이 있습니다.

vector의 구조

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 배열이 해제되더라도 값을 잘 전달 받을 수 있었던 것입니다.

Categories:

Updated:

Leave a comment