안녕하세요. 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와는 상관이없습니다.
- 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는 다릅니다.
size는 할당된 메모리 안에 요소가 들어있는것의 갯수.
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 |
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/
'<개인공부> > [C++]' 카테고리의 다른 글
[C++] multiset container 정리 및 사용법 (0) | 2017.07.27 |
---|---|
[C++] set container 정리 및 사용법 (4) | 2017.07.26 |
[C++] list container 정리 및 사용법 (1) | 2017.07.25 |
[C++] deque container 정리 및 사용법 (2) | 2017.07.23 |
[C++] vector container 정리 및 사용법 (34) | 2017.07.20 |
[C++] STL 이란. (0) | 2017.07.19 |
[C++] Pair 클래스 정리 및 예제 (vector, sort) (3) | 2017.07.18 |
[C++] 예외처리 (Exception Handling, try catch) (2) | 2017.07.14 |
[C++] template(템플릿)에 관하여 2 (클래스 템플릿, 템플릿 특수화) (0) | 2017.07.12 |
설명이 엄청 잘 되어 있어요!
잘 보고 갑니다
답글
정말 감사합니다 !!
감사합니다 함수부분좀 개인 블로그에 퍼가서 혼자 참고할게요!
답글
대단해요 어떻게 혼자서 공부할 생각을 하셨어요..?
맘 잡고 하려고 해도 정말 안됩니다..
조금하다가 말게되고 그러네요...
뭐 하나 제대로 하고 있지 않은 느낌입니다..ㅠ
답글
맘 잡고 하다가 안되면 쉬시고
다시 또 맘 잡고 하다가 안되면 쉬면서
꾸준히 하다안하다 하다 안하다만 반복해도 재미있을거에요!
아예 안하는것보다는 맘잡고 조금이라도 했다는게 중요한거죠! 첫 발을 내딛었으면 속도가 중요하지 않습니다
천천히 꾸준히 하면됩니다. 쉬고 싶으면 쉬고 한발가고 쉬고 한발가고 쉬고
하셔도 많이 많이 늘으실거에요!
그리고 공부한걸 저처럼 남겨보세요!
그러면 하나하나 쌓이는걸 "눈으로" 보면 '내가 이만큼이나 했나? ' 생각도 들고 정말 정말 아무도 설명할 수 없는 성취감이 느껴집니다.
설명이 너무 깔끔합니다. 이해가 아주 잘되네요.
답글
도움이 되어서 정말 기분 좋습니다.
자주 방문 부탁드립니다.
감사합니다.
정리도 정리지만 언어구사가 아름다우시네요,..
다른분들 답댓 달아주신거 보고 저도 힘을 얻는 기분입니다 ㅎ
훌륭한 개발자 되실거같네요
저도 덕분에 벡터에 대해 알아갑니다 ㅎㅎ
답글
행인님
제가 행인님께 도움이 되어서 기분이 좋습니다
좋은 내용 가지고 기다리겠습니다
또방문해주세요~!
안녕하세요 블록디마스크님
항상 블로그를 통해 도움을 많이 받고있습니다
이번 글도 정말 잘 읽었어요!
그런데 벡터의 capacity 에 대한 설명에 추가되면 더 좋을 것 같은 의견이 있어서 말씀 드려보려고 해요!
벡터의 사이즈는 2^n으로 늘어난다고 설명해주셨는데.
벡터의 용량(capacity)은 원소의 개수(size)가 용량과 같아졌을 경우!, 기존 용량의 2배로 재할당합니다!
그리고 이처럼 용량을 키울 경우 용량이 2배된 새로운 벡터를 만들고 거기에 값을 이동(move semantics, std::move)시킵니다. 이 이동의미론 덕분에기존 원소들을 모두 복사하지 않고 새로운 벡터에 기존 원소들의 포인터를 이동(std::move)시킴으로써 복사할 때의 오버헤드를 줄일 수 있게 되었습니다.
답글
추가 설명 감사합니다.
추후 내용에 포함시키도록하겠습니다.
캬~~~ 정리 감사합니다
프로그래머스 문제 푸려고 vector 없이 코드 짜가지고 넣었는데 컴파일러가 인식을 못하더라구요
그래서 vector좀 알아보려고 왔는데 졸라 편한거였네요
정말 좋은 정보 정리도 잘하시네요
드릴게 하트 밖에 없는게 아쉽네요
답글
네 vector 컨테이너는 격하게 편합니다. 감사합니다.
정리가 잘되어 있어서 이해하기 편하네요
vector 개념이 필요할 때 이 글 보면 될 것 같네요ㅎㅎ
답글
절미짱님 방문 감사합니다.
너무 감사합니다.
정말 큰 도움이 되었어요!
답글
감사합니다.
비밀댓글입니다
답글
crescent님 네 학습용이기 때문에 상관없습니다. 다만 출처를 남겨주시면 감사하겠습니다.
개발자님 혹시 벡터를 10개로 할당하고 10개의 요소가 꽉차 있는 상태에서 push_back을 하여 마지막에 요소하나를 추가한다면 맨 첫번째 요소는 밀려나서 사라지게 되나요??
답글
찾아봤는데 capacity가 1씩 증가하는 형태더라구요..
capacity를 10개로 선언하고
마지막에 데이터가 하나 추가되면 맨 처음이 삭제되는 식의 벡터는 어떻게 코딩해야 할까요 ㅜㅜ 알려주시면 감사하겠습니다!
C++에 큐(queue)라는 컨테이너 혹은 덱(deque)이라는 컨테이너가 있습니다.
둘다 뒤에서 넣고 앞에서 뺄 수 있는 first in first out 이 가능합니다.
vector 컨테이너는 first in last out 구조의 스택 형식과 비슷한 구조이므로 문의 주신 기능을 하기엔 적절하지 않은 구조로 판단됩니다.
제 블로그에도 정리 되어있으니 참고하셔도 좋을것 같습니다. 감사합니다.
vector도 c++에서 이미 잘 구현된 클래스라고 볼 수 있는건가요?
답글
안녕하세요. Hi님
vector가 C++ 표준 라이브러리에 등록 되어있으니, 이미 인증되어있다고 봐야하는게 아닌가 싶습니다.
완전 도움 먾아 되었어요 !감사합니다!
답글
방문 감사합니다. 또오세요
와.. 이렇게 잘 정리해 주시다니 ㄷㄷ
덕분에 vector에 대해 잘 알고 갑니다!!!
답글
감사합니다.
더 좋은 글로 기다리겠습니다.
avast에서 URL:Blacklist에 감염됐다면서 사진이 안뜨네요...
답글
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/
설명 정말 이해하기 쉽게 잘하셨네요. 덕분에 vector 이해하고 갑니다. ^^
답글
제 글이 도움이 되어 다행입니다.
감사합니다.
vector 뿐만 아니라 다른 주제도 매번 BlockDMask님 블로그 참고합니다.
설명과 정리를 너무 잘해주셔서 정말 감사합니다!
답글