본문 바로가기
<개인공부>/[C++]

[C++] vector container 정리 및 사용법

by 사용자 BlockDMask 2017. 7. 20.
반응형

안녕하세요.  BlockDMask 입니다.

오늘은 C++ STL의 sequence container 중에 정말 자주 쓰는 vector에 대해서 알아보겠습니다.

<목차>

1) vector container 란?

2) vector의 사용 

3) vector의 생성자와 연산자

4-1) vector의 멤버 함수
4-2) vector의 size와 capacity와의 관계 (중요!)

5) vector의 멤버 형식
6) vector를 사용하는 다양한 예제


1) vector container 란?

  • vector 컨테이너는 자동으로 메모리가 할당되는 배열. 이라고 생각하면 될거같습니다.
    저는 C를 하다가 C++로 넘어와서 이렇게 vector 컨테이너를 처음 접하고 정말 소름이 돋았었습니다.
    자동으로 메모리를 할당해주고 알아서 끝에 들어가주고 알아서 삭제도 해주고,,,, 정말 효자 컨테이너입니다.

  • 모든 STL 이 그렇듯. template를 사용하기 때문에 데이터 타입은 마음데로 넣을 수 있습니다.

  • 간단하게 그림으로 구조를 먼저 보고 넘어가겠습니다. (약간 자료구조 스택과 비슷한 느낌입니다.)

  • 이러한 구조를 가지고있으며, 맨 뒤쪽에서 삽입과 삭제가 가능합니다.

  • 중간에 값을 삽입 하거나 삭제할 수도 있습니다. 하지만 배열기반이으로 삽입 삭제가 빈번하게 일어난다면 비효율적 입니다.

2) vector 의 사용.

  • <vector> 헤더파일을 추가해야합니다.
  • using namespace std; 를 해주면 편리합니다.
  • vector의 선언은 - vector<[data type]> [변수이름] 입니다.
    ex) vector<int> v;

3) vector의 생성자와 연산자. (편의상 int를 사용하겠습니다.)

  • vector<int> v;
    - 비어있는 vector v를 생성합니다.

  • vector<int> v(5);
    - 기본값(0)으로 초기화 된 5개의 원소를 가지는 vector v를 생성합니다.

  • vector<int> v(5, 2);
    - 2로 초기화된 5개의 원소를 가지는 vector v를 생성합니다.

  • vector<int> v1(5, 2);
    vector<int> v2(v1);
    - v2는 v1 vector를 복사해서 생성됩니다.
  • vector<int> v1; , vector<int> v2;  가 있고, 내부에 인자들이 있다고 했을때.

    연산자 : "==", "!=", "<", ">", "<=", ">=" 로 대소비교 가 가능합니다.

4) vector의 멤버 함수

== vector<int> v; 라고 가정.
== 참조 한다는 것은 해당 데이터를 리턴 한다는 뜻입니다.

  • v.assign(5, 2);
    - 2의 값으로 5개의 원소 할당.

  • v.at(idx);
    - idx번째 원소를 참조합니다.
    - v[idx] 보다 속도는 느리지만, 범위를 점검하므로 안전합니다.

  • v[idx];
    - idx 번째 원소를 참조합니다.
    - 범위를 점검하지 않으므로 속도가 v.at(idx)보다 빠릅니다.

  • v.front();
    - 첫번째 원소를 참조합니다.

  • v.back();
    - 마지막 원소를 참조합니다.

  • v.clear();
    - 모든 원소를 제거합니다.
    - 원소만 제거하고 메모리는 남아있습니다.
    - size만 줄어들고 capacity는 그대로 남아있습니다.

  • v.push_back(7);
    - 마지막 원소 뒤에 원소 7을 삽입합니다.

  • v.pop_back();
    - 마지막 원소를 제거합니다.

  • v.begin();
    - 첫번째 원소를 가리킵니다. (iterator와 사용)

  • v.end();
    - 마지막의 "다음"을 가리킵니다 (iterator와 사용)

  • v.rbegin();
    - reverse begin을 가리킨다 (거꾸로 해서 첫번째 원소를 가리킵니다)
    - iterator와 사용.

  • v.rend();
    - reverse end 을 가리킨다 (거꾸로 해서 마지막의 다음을 가리킵니다)
    - iterator와 사용.

  • v.reserve(n);
    - n개의 원소를 저장할 위치를 예약합니다(미리 동적할당 해놉니다)

  • v.resize(n);
    - 크기를 n으로 변경한다.
    - 더 커졌을 경우 default값인 0으로 초기화 한다.
  • v.resize(n,3);
    - 크기를 n으로 변경한다.
    - 더 커졌을 경우 인자의 값을 3으로 초기화한다.



  • v.size();
    - 원소의 갯수를 리턴한다.

  • v.capacity();
    - 할당된 공간의 크기를 리턴한다.
    - 공간 할당의 기준은 점점 커지면서로 capacity를 할당하게 됩니다.
    **size와 capacity에 관계는 4번 항목에서 설명드립니다. 중요하니 꼭 보고 가세요
  • v2.swap(v1);
    - v1과 v2의 원소와 capacity 바꿔줍니다. (모든걸 스왑해줌)
    - v1의 capacity를 없앨때 (할당한 메모리를 프로그램이 끝나기 전에 없애고 싶을때) 사용하기도 합니다.
    - v2를 capacity가 0인 임시 객체로 만들어서 스왑을 해줍니다.
    - vector<int>().swap(v1);

  • v.insert(2, 3, 4);
    - 2번째 위치에 3개의 4값을 삽입합니다. (뒤엣놈들은 뒤로 밀림)

  • v.insert(2, 3);
    - 2번째 위치에 3의 값을 삽입합니다.
    - 삽입한 곳의 iterator를 반환합니다.

  • v.erase(iter);
    - iter 가 가리키는 원소를 제거합니다.
    - size만 줄어들고 capacity(할당된 메모리)는 그대로 남습니다.
    - erase는 파라미터 하나를 받을때와 두개를 받을 때 다릅니다.
    - 그에 따른 예제는 여기있습니다.
  • v.empty()
    - vector가 비었으면 리턴 true
    - 비어있다의 기준은 size가 0이라는 것이지, capacity와는 상관이없습니다.
4) vecotr의 size와 capacity와의 관계 (중요!)
  • v.size();
    - 원소의 갯수를 리턴한다.

  • v.capacity();
    - 할당된 공간의 크기를 리턴한다.
    - 공간 할당의 기준은 점점 커지면서로 capacity를 할당하게 됩니다.
    - dev c++ 기준으로 string 클래스로 vector 를 만들었을때.
    원소 갯수 1 => capacity 1
    원소 갯수 2 => capacity 2
    원소 갯수 3 => capacity 4
    원소 갯수 4 => capacity 4
    원소 갯수 5 => capacity 8
    원소 갯수 6 => capacity 8
    원소 갯수 7 => capacity 8
    원소 갯수 8 => capacity 8
    원소 갯수 9 => capacity 16
    을 봐서는 2^n으로 capacity의 메모리 할당이 되지 않나 싶습니다.(아래에서 테스트 해보겠습니다)
  • 기존 메모리의 * 2 로 증가하게 됩니다.
  • 이런식으로 메모리 할당을 하는 이유는 push_back이 일어날때 마다 동적할당을 하면,
    비효율적이므로 미리 정해둔 만큼 동적할당을 한번에 하는 것
    입니다.
  • 원소 개수가 증가하면서, 메모리를 증가해서 따로 할당하게 되면 
    기존위치에 메모리를 이어서 할당하는게 아니라 새롭게 메모리를 할당해서 원소들을 전부 복사하는 형태인데요.
    기존에는 복사에 대한 비용이 많이 들었었습니다. 하지만, 
    std::move 라는 것이 도입되면서 복사하지 않고 이동하게 되어 메모리 증가에 따른 비용이 많이 들지 않게 되었습니다.

**capacity와 size는 다릅니다. 
s
ize는 할당된 메모리 안에 요소가 들어있는것의 갯수.
capacity는 할당된 메모리의 갯수? 크기.


이해가 쉽게 되도록 그림을 그려보았습니다.



예시 0) vector size, capacity 에 대한 TEST

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
#include<vector>
using namespace std;
 
int main(void){
    vector<int> v;
    
    cout << "[ v[i] , v.size(), v.capacity() ] " << endl
    for(int i=0; i<=64; i++){
        v.push_back(i+1);
        cout << "[" << v[i] << " , " << v.size() << " , " << v.capacity() << "]" << endl;
    }
    return 0;    
}
cs


> vector의 size() capacity() 테스트 결과


> 테스트로 확인결과.
size는 데이터가 채워진 원소의 갯수 이고, capacity 는 할당된 메모리 공간임을 알 수 있었습니다.
또한, 기존메모리 * 2로 capacity가 증가함을 알 수 있었습니다.
test 환경은, dev c++, win7 x64 이었습니다.

5) vector의 멤버 형식

  • iterator - 반복자 형식
  • reverse_iterator - 역 반복자 형식
  • value_type - 원소의 형식
  • size_type - 원소의 개수의 형식

6) vector의 조금 다양한 예시.


예시 1,2,3) 다양한 vector [], at, iterator, size_type 이용한 접근 방법 및 출력 방법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<iostream>
#include<vector>
using namespace std;
 
int main(void){
    vector<int> v;
    
    v.push_back(21);
    v.push_back(32);
    v.push_back(53);
    v.push_back(64);
    v.push_back(15);
    
    
    //ex1) 멤버형식 size_type 이용한 반복.
    cout << "ex1-1) [v.at(i)] size_type : " ;
    for(vector<int>::size_type i =0; i<v.size(); i++){
        cout << v.at(i) << " ";
    }
    cout << endl;
    cout << "ex1-1) [ v[i] ] size_type : " ;
    for(vector<int>::size_type i =0; i<v.size(); i++){
        cout << v[i] << " ";
    }
    cout << endl << endl;
    
    
    //ex2) int i 를 이용한 반복.
    cout << "ex2-1) [v.at(i)] int : " ;
    for(int i =0; i<v.size() ; i++){
        cout << v.at(i) << " ";
    }
    cout << endl;
    cout << "ex2-2) [ v[i] ] int : " ;
    for(int i =0; i<v.size() ; i++){
        cout << v[i] << " ";
    }
    cout << endl << endl;
    
    
    //ex3) 반복자 iterator를 이용한 반복. 
    cout << "ex3) [*iter] iterator : ";
    vector<int>::iterator iter;
    for(iter = v.begin(); iter != v.end() ; iter++){
        cout << *iter << " ";
    }
    cout << endl << endl;
    
 
    return 0;
}
cs


>예시 1,2,3의 결과



예시 4, 5, 6) 삽입 삭제 size,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include<iostream>
#include<vector>
#include<string>
using namespace std;
 
int main(void){
    vector<string> v;
    
    v.push_back("Show Me");
    v.push_back("Tiger JK");
    v.push_back("Dok2");
    v.push_back("GAEKO");
    v.push_back("ZICO");
 
    //ex4) v.front(), v.back() 
    cout << "//ex4) v.front(), v.back()" << endl;
    
    cout << "v.front() : " << v.front() << endl;
    cout << "v.end() : " << v.back() << endl;
    cout << endl;
    
    
    
    
    //ex5) v.popback()
    cout << "//ex5) v.popback()" << endl;
    
    vector<string>::iterator iter; 
    for(iter = v.begin(); iter != v.end() ; iter++){
        cout << *iter << " / " ;
    }
    cout << endl;
    
    v.pop_back();
    
    for(iter = v.begin(); iter != v.end() ; iter++){
        cout << *iter << " / " ;
    }
    cout << endl;
    cout << endl;
 
    
        
    
    //ex6) v.erase(iter);
    cout << "//ex6) v.erase(iter)" << endl;
    
    for(iter = v.begin(); iter != v.end() ; iter++){
        if(*iter == "Dok2"){
            v.erase(iter);
            break;
        }
    }
    for(iter = v.begin(); iter != v.end() ; iter++){
        cout << *iter << " / " ;
    }
 
    
    
    cout << endl << endl;
    //ex7) v.size(), v.capacity();
    cout << "//ex7) v.size(), v.capacity()" << endl;
    
    cout << "v.size() : " << v.size() << endl;
    cout << "v.capacity() : " << v.capacity() << endl;
    
    return 0;
}
cs


>예제 4, 5, 6 결과


참고 : http://www.cplusplus.com/reference/vector/vector/

반응형

댓글37

  • Anonymous 2018.04.11 04:07

    설명이 엄청 잘 되어 있어요!
    잘 보고 갑니다
    답글

  • 2018.09.09 16:56

    감사합니다 함수부분좀 개인 블로그에 퍼가서 혼자 참고할게요!
    답글

  • 2018.09.19 21:04

    대단해요 어떻게 혼자서 공부할 생각을 하셨어요..?
    맘 잡고 하려고 해도 정말 안됩니다..
    조금하다가 말게되고 그러네요...
    뭐 하나 제대로 하고 있지 않은 느낌입니다..ㅠ
    답글

    • 맘 잡고 하다가 안되면 쉬시고
      다시 또 맘 잡고 하다가 안되면 쉬면서
      꾸준히 하다안하다 하다 안하다만 반복해도 재미있을거에요!

      아예 안하는것보다는 맘잡고 조금이라도 했다는게 중요한거죠! 첫 발을 내딛었으면 속도가 중요하지 않습니다
      천천히 꾸준히 하면됩니다. 쉬고 싶으면 쉬고 한발가고 쉬고 한발가고 쉬고
      하셔도 많이 많이 늘으실거에요!

      그리고 공부한걸 저처럼 남겨보세요!
      그러면 하나하나 쌓이는걸 "눈으로" 보면 '내가 이만큼이나 했나? ' 생각도 들고 정말 정말 아무도 설명할 수 없는 성취감이 느껴집니다.

    • Favicon of https://rolypolytoy.tistory.com rolypolytoy 2021.03.24 12:02 신고

      인터뷰준비한다고 들어왔는데, 깔끔하게 정리가 잘되어있습니다. blockmask님 말씀대로 안잡힐땐 쉬었다가 틈틈히 하는 것에 공감이 되네요. 재밌어하는 날에는 또 집중해서 빠짝공부하게되더라고요.. blockmask님 멋있습니다.

  • Favicon of http://sadffadf 건국대 종신 2018.10.19 23:39

    설명이 너무 깔끔합니다. 이해가 아주 잘되네요.
    답글

  • 행인1 2019.07.15 17:34

    정리도 정리지만 언어구사가 아름다우시네요,..
    다른분들 답댓 달아주신거 보고 저도 힘을 얻는 기분입니다 ㅎ
    훌륭한 개발자 되실거같네요
    저도 덕분에 벡터에 대해 알아갑니다 ㅎㅎ
    답글

  • Favicon of http://artbooks.tistory.com YoongYoong 2019.07.22 07:54

    안녕하세요 블록디마스크님
    항상 블로그를 통해 도움을 많이 받고있습니다
    이번 글도 정말 잘 읽었어요!
    그런데 벡터의 capacity 에 대한 설명에 추가되면 더 좋을 것 같은 의견이 있어서 말씀 드려보려고 해요!

    벡터의 사이즈는 2^n으로 늘어난다고 설명해주셨는데.

    벡터의 용량(capacity)은 원소의 개수(size)가 용량과 같아졌을 경우!, 기존 용량의 2배로 재할당합니다!

    그리고 이처럼 용량을 키울 경우 용량이 2배된 새로운 벡터를 만들고 거기에 값을 이동(move semantics, std::move)시킵니다. 이 이동의미론 덕분에기존 원소들을 모두 복사하지 않고 새로운 벡터에 기존 원소들의 포인터를 이동(std::move)시킴으로써 복사할 때의 오버헤드를 줄일 수 있게 되었습니다.
    답글

  • tongstar 2020.03.29 02:59

    캬~~~ 정리 감사합니다
    프로그래머스 문제 푸려고 vector 없이 코드 짜가지고 넣었는데 컴파일러가 인식을 못하더라구요
    그래서 vector좀 알아보려고 왔는데 졸라 편한거였네요
    정말 좋은 정보 정리도 잘하시네요
    드릴게 하트 밖에 없는게 아쉽네요
    답글

  • 절미짱 2020.04.24 15:51

    정리가 잘되어 있어서 이해하기 편하네요:) vector 개념이 필요할 때 이 글 보면 될 것 같네요ㅎㅎ
    답글

  • well 2020.06.04 10:52

    너무 감사합니다.
    정말 큰 도움이 되었어요!
    답글

  • 2020.07.10 14:36

    비밀댓글입니다
    답글

  • kk 2020.08.14 17:34

    개발자님 혹시 벡터를 10개로 할당하고 10개의 요소가 꽉차 있는 상태에서 push_back을 하여 마지막에 요소하나를 추가한다면 맨 첫번째 요소는 밀려나서 사라지게 되나요??
    답글

    • kk 2020.08.14 20:20

      찾아봤는데 capacity가 1씩 증가하는 형태더라구요..
      capacity를 10개로 선언하고
      마지막에 데이터가 하나 추가되면 맨 처음이 삭제되는 식의 벡터는 어떻게 코딩해야 할까요 ㅜㅜ 알려주시면 감사하겠습니다!

    • C++에 큐(queue)라는 컨테이너 혹은 덱(deque)이라는 컨테이너가 있습니다.
      둘다 뒤에서 넣고 앞에서 뺄 수 있는 first in first out 이 가능합니다.
      vector 컨테이너는 first in last out 구조의 스택 형식과 비슷한 구조이므로 문의 주신 기능을 하기엔 적절하지 않은 구조로 판단됩니다.
      제 블로그에도 정리 되어있으니 참고하셔도 좋을것 같습니다. 감사합니다.

  • hi 2020.09.03 01:17

    vector도 c++에서 이미 잘 구현된 클래스라고 볼 수 있는건가요?
    답글

  • tonytheballone 2020.09.11 12:45

    완전 도움 먾아 되었어요 !감사합니다!

    답글

  • boj.kr 2020.11.03 20:31

    와.. 이렇게 잘 정리해 주시다니 ㄷㄷ
    덕분에 vector에 대해 잘 알고 갑니다!!!
    답글

  • 대파 2020.11.24 07:33

    avast에서 URL:Blacklist에 감염됐다면서 사진이 안뜨네요...
    답글

    • 대파 2020.11.24 07:39

      img1.daurncdn.net연결을 중단한다면서 결과창이 안보입니다

    • 안녕하세요.
      제 블로그에 따로 의심가는 이상한 짓?을 해놓지는 않았습니다.
      성실하고 깨끗하게 사용하고 있는데 이상하네요.

      검색을 해보니 avast가끔씩 오진(?)을 하는 경우도 있다고 하는데, 정확한것은 avast쪽에 문의해주시는게 더 좋을것 같습니다.

      참고
      - https://forum.avast.com/index.php?topic=237179.0
      -
      - https://m.maplestory.nexon.com/Community/Free/52130
      -https://www.reddit.com/r/avast/comments/io9jaq/consistent_urlblacklist_notification_whilst_using/

  • ㅇㅇㅇ 2020.12.01 20:11

    설명 정말 이해하기 쉽게 잘하셨네요. 덕분에 vector 이해하고 갑니다. ^^
    답글

  • einfach991 2021.02.17 02:15

    vector 뿐만 아니라 다른 주제도 매번 BlockDMask님 블로그 참고합니다.

    설명과 정리를 너무 잘해주셔서 정말 감사합니다!
    답글

  • ㅇㅇ 2021.03.19 17:30

    너무 이해가 잘돼요
    답글

  • Favicon of https://what-am-i.tistory.com 처음처럼1010 2021.05.14 21:51 신고

    좋은 포스팅 감사합니다!
    답글