삽질의 현장/- C++

#017_시(c)시(c)해서 C++?!_STL_Vector 맛보기

shovelman 2015. 7. 15. 00:20

안녕하세요 삽잡이입니다.


오늘부터는 STL(Standard Template Library) 에 대해서 배워보려고 합니다..


STL 이란 Standard Template Library 즉, 표준 라이브러리입니다...

STL은 여러가지의 자료구조 클래스와 알고리즘 등을 반복자를 통해 접근 하여

사용할 수 있는 라이브러리 입니다...


우선 이에 들어가기 전에 템플릿에 대해 간략하게 소개를 하고자 합니다.

템플릿이란 사전적으로 '틀'이라는 뜻을 가지고 있습니다.


'틀'이라고 하는 것은 무엇인가를 만들어줄 수 있는 기능을 가지고 있습니다.

즉, 템플릿은 진짜 코드를 만들어 줄 수 있는 가상의 코드입니다.

호출하면서 인자를 다양하게 전달을 하는 것이고,

컴파일러는 다양하게 전달한 인자를 하나하나 만들게 되죠...

참고로... 템플릿 코드는 헤더에 정의하는 것이 일반적입니다.


템플릿에 대해서 언급한 이유는 STL은 템플릿 형식으로

지원하고 있기 때문이죠...


아무튼... 우리는 여기에 사로잡혀 있어서는 안됩니다...



STL 이라는 표준 템플릿 라이브러리에는 

객체들을 저장하는 컨테이너와 컨테이너에 저장된 요소들에 접근할 수 있는 반복자

그리고 머리아픈... 알고리즘으로 구성되어 있습니다...

알고리즘 같은 경우에는 계산적인 절차 

즉, 문제를 해결하기 위한 단계들을 묶어 놓은 것인데요...


쉽게 추가, 검색, 삭제. 복사 등 

각각의 문제를 해결하기 위한 방법을 만들어 놓은 것들입니다...


그리고 함수자가 있습니다...  함수처럼 사용할 수 있는 객체...

이는 나중에 추가적으로 설명하도록 하겠습니다...


C++에서 제공하는 무기죠.... 허허.. 

무기 하나, 자료를 보관할 때 사용한다던 컨테이너 클래스...  

그 중에서 컬렉션 (자료구조) 들에는

vector(배열), list(연결 리스트), set, map(이진 탐색트리), 

stack, queue, deque 등이 정의되어 있습니다.


무기 둘, 이를 탐색할 수 있도록 반복자... 

반복자는 컨테이너에 접근 할 수 있는 녀석이라고 했습니다... 포인터와 닮았는데요...

말 그대로 iterator는 반복자라고 사전에 정의되어 있군요...


이... iterator라고 하는 반복자 녀석은 포인터와 닮았는데 정확히 말하자면

포인터를 감싸고 있는 형식의 친구입니다...

사용자가 컨테이너의 요소에 함부로 접근하여 뭔짓을 할지 모르기에

public 으로 요소를 참조하는 참조형 멤버 변수( *member )를 만들고 

요소만 볼 수 있고 직접적인 접근을 차단하는 것입니다...


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
 
template <typename Element>
class vector
{
// ... 중략 ...
 
public:    
    class iterator
    {
        Element *pos;
 
//... 중략 ...
 
 
cs


이와 같이 말입니다...

*(pos) 멤버 변수를 통해서 요소의 주소 안에 있는 값을

참조할 수 있는 것이죠... 


따라서 이 iterator 안에는 요소에 접근하여 값을 참조할 수 있는 간접 연산자 (*),

그 다음 위치 혹은 그 이전 위치들을 참조할 수 있도록 증/감연산자(+/-, ++/--),

그리고 요소의 시작과 끝 그 외 확인을 위한 비교연산자(==/!=)

가 연산자 오버로딩 즉, 중복정의 되어있습니다...

참고로 인덱스 연산은 중복정의 되어있지 않습니다...


앗... 쉽게 쉽게 맛만보는 것인데.... 이해가 가지 않으신다면 잊어버리세요...

결국 iterator라는 것은 포인터와 비슷한데 사용자가 함부로 요소에 접근하지 못하도록

포인터에 보호막을 감싼(?) 개념이라고 이해하시면 될 것 같습니다...

자체를 반환한다면 위험하기에 정보은닉을 하는 것이지요...


아무튼...


무기 셋, 정렬, 삭제, 병합 등등등 문제를 해결하기 위한 방법들... 즉... 다양한 알고리즘...


그리고 마지막으로 함수자...



지금부터 우리는 컨테이너의 종류 중 하나인

백터에 대해서 알아보려고 합니다...


벡터(Vector)는 STL 컨테이너에서 많이 쓰이는 컨테이너중 하나라고 합니다...

우리가 기존에 배우던 C/C++의 배열과 비슷하게

연속적인 메모리를 소유하고 있기에

연속 메모리 기반이라고 할 수 있습니다. 

하지만 재미있는 것은 데이터가 저장될 수록 메모리가 자동적으로 증가하게 됩니다.


기존에 C/C++에서 배우던 배열과 같은 경우에는

배열의 크기는 상수이기 때문에 

동적으로 메모리를 할당받아 생성하는 경우가 다반사였는데요,


이 또한 동적으로 할당 받은 메모리 사이즈마져도

한번 할당되면 크기를 변경하지 못하는 특징이 있었습니다.

왜냐하면 '나 이만한 크기로 메모리 할당해줘...' 하면 

그 만큼의 메모리를 힙에서 할당해오는 것이었으니까요...


벡터(vector)와 같은 경우에는 메모리가 자동적으로 증가한다고 말씀드린 것이...

기존의 메모리를 삭제하고 새로운 메모리를 재할당하기 때문에

이와 같이 설명드렸던 것입니다...



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
 
 
#include <iostream>
#include <vector>
using namespace std;
 
typedef vector<int>::iterator Iter;
void View(vector<int> &arr)
{
    cout << "저장소 용량:" << arr.capacity();
    cout << " 보관 개수:" << arr.size()<<endl;
    Iter seek = arr.begin();
    Iter end = arr.end();
    for (; seek != end++seek)
    {
        cout << "값: "<<(*seek) << endl;
    }
}
 
void Sequence()
{
    vector<int> arr;
    View(arr);
    arr.push_back(3);
    View(arr);
    arr.push_back(6);
    View(arr);
    arr.push_back(3);
    View(arr);
    arr.push_back(1);
    View(arr);
    arr.push_back(5);
    View(arr);
    arr.push_back(3);
    View(arr);
    arr.push_back(7);
    View(arr);
}
 
void main()
{
    Sequence();
}
 
 
cs

         


vector를 사용하기 위해서는 당연하게 헤더 파일을 포함시켜야합니다...

저는... vector<int> 

즉, vector int형에 대해서 선언을 했습니다.

또한 vector의 주요 멤버 중 iterator (반복자)를 선언하기 번거로워 

비교적 간단한 별명을 붙였습니다...


실행을 시켜보시면 알겠지만,

메모리가 부족하면 스스로 메모리를 확장해줍니다...

정확하게 말하자면 메모리를 재할당하는 것이지요...


근데 말입니다... 재미있는 것은 메모리를 확장할 때 1씩 증가하다가 

이게 양이 많아질 수록 메모리 확보를 하는 수가 증가합니다


정확하게 말씀드리자면, 

컴파일러가 계속해서 메모리를 재할당하는 일에 대한 비효율성을 막기위해

메모리 재할당을 하다가 여유 메모리를 추가적으로 더 할당을 해줍니다...



재미있군요...

뭔지 모르시겠지만 하나하나 차근차근 알아가보도록 하죠...


기억하셔야 할 것은,

지금 우리가 알아보고 있는 것은 자료구조 배열(벡터)을 알아보고 있는 것입니다...

여기서 말하는 배열은 

우리가 기존에 사용하던 배열과 달리 저장소의 크기가 동적인 배열이죠...

runtime에 결정할 수 있는 '동적 배열', 

저장소가 부족하면 확장하는 '확장배열' 이라고 할 수 있습니다...

완전한 동적 확장 배열을 말하는 것이지요 ㅎㅎ


와... 재미있다!


허허... 삽잡이였습니다...