티스토리 뷰
가변배열은 흔히 C#이나 JAVA와 같은 언어에서만 사용하는데, C++에서도 구현할 수 있습니다.
오늘은 가변배열이 무엇인지, 어떻게 사용할 수 있는지 알아보고 풀 소스까지 공개하겠습니다.
가변배열(Dynamic Array)
1 2 3 | int array[num]; //또는 int a[] = new input[num]; | cs |
C나 C++에서는 위와같이 배열의 크기를 사용자로부터 입력받는 코드는 작성할 수 없습니다. 그런데 우리는 배열을 생성할때 몇개의 방을 만들어야 할지 잘 모르지요. 가장 간단한 방법은
1 | int array[1000]; | cs |
이와같이 무식하게 큰 크기의 배열을 정적으로 만드는것. 그러나 만약 1000개 중에 10개 20개만 사용이 된다면, 나머지 900개가 넘는 메모리들은 전부 버려지는 것이 됩니다. 그렇기 때문에 꼭 필요한 만큼만, 혹은 입력되는 데이터보다 약간 큰 정도로 배열을 만드는것이 좋은데, 앞서 이야기 했듯이 C#이나 JAVA에서는 기본적인 문법으로 이를 제공 하나, C, C++에서는 불가능 하기 때문에 임의의 클래스로 생성해야 합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class dynamicArray { private: int* m_array; int m_size; int m_used; public: dynamicArray(); dynamicArray(int size); ~dynamicArray(); void popBack(); void pushBack(int data); void print(); int &operator[](int index); }; | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | dynamicArray::dynamicArray() : m_size(1), m_used(0) { m_array = new int[m_size]; } dynamicArray::dynamicArray(int size) : m_size(size), m_used(0) { m_array = new int[m_size]; } dynamicArray::~dynamicArray() { delete[] m_array; } | cs |
소멸자는 클래스가 소멸할때 실행이 되는 함수입니다. 앞서 말씀드렸듯이 사용이 끝난 메모리는 반드시 해제를 해야 합니다. new는 delete로 new []는 delete[]로 해제하면 됩니다. 소멸자에서는 delete함수를 이용하여 할당되었던 메모리를 돌려보냅니다.
다음으로 pushBack 함수에 대해 알아보겠습니다.
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 | void dynamicArray::pushBack(int data) { if(this->m_used < this->m_size) { this->m_array[this->m_used] = data; } //메모리가 있으면 else { int* temp = new int[m_size]; for(int i=0; i<this->m_used; i++) temp[i] = this->m_array[i]; delete[] this->m_array; this->m_size *= 2; this->m_array = new int[m_size]; //this->m_array = temp; for(int i=0; i<this->m_used; i++) { this->m_array[i] = temp[i]; } delete[] temp; this->m_array[this->m_used] = data; } this->m_used++; //메모리가 없으면(더이상 넣을 공간이 없으면 확장) } | cs |
int 형의 data를 전달인자로 받습니다. 이때 가장 먼저 이 data를 배열에 추가하기 위해 배열에 빈 방이 있는지 확인합니다.
m_size가 배열의 방 갯수, m_used가 사용중인 방의 갯수라고 했으니 m_used가 m_size보다 작으면 빈방이 있는 것이겠죠, 그럼 m_array의 마지막 방의 인덱스인 m_used번 방에 data를 넣고 m_used를 1 증가시킨채로 리턴하고 종료합니다. 간단하죠
그러나 이렇게 데이터를 추가시키다 보면 메모리가 가득차서 더이상 넣을 수 없을때 즉, m_used가 m_size보다 같거나 클때가 올 것입니다. 이때 else문으로 빠지게 됩니다. 한번 살펴보도록 하지요. 가장먼저 int* temp 를 선언과 동시에 초기화 했는데, m_array와 똑같은 방의 갯수를 가진 배열을 한개 더 선언한 것입니다.
그리고 for문을 통하여 m_array의 데이터를 모두 temp배열에 복사하게 되죠.
다음으로 지금까지 사용하던 m_array의 메모리를 과감하게 해제해 줍니다. 왜냐하면 작은집을 무너뜨리고 큰 집을 짓듯이 더 크게 지을거니까....
m_size의 크기를 2배로 늘려줍니다. 그리고 m_array에 새 집을 짓습니다.
메모리 할당을 집짓기에 비유했는데, 이미 해당 자리에 집이 지어져있으면 새 집을 지을 수 없듯이 메모리가 할당된곳에 다시 메모리를 할당할 수 없습니다. 반드시 해제하고 해야 합니다.
그리고 다시 for문을 통해서 temp배열에 있던 데이터들을 m_array로 옮겨줍니다. 그리고 temp배열을 해제하고 마지막방에 data를 넣은다음, m_used를 하나 증가시키면 끝.
공간이 부족하다 -> 데이터를 임시배열에 복사한다 -> 배열을 없에고 더 큰 배열을 만든다 -> 임시배열에서 다시 복사한다 순의 진행이 되겠습니다.
popBack 함수도 살펴보도록 하겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | void dynamicArray::popBack() { if (m_used == 0) return; m_used--; int* temp = new int[m_used]; for (int i = 0; i < m_used; i++) temp[i] = m_array[i]; delete[] m_array; m_array = new int[m_size]; for (int i = 0; i < m_used; i++) temp[i] = m_array[i]; delete[] temp; return; } | cs |
pushBack 함수의 흐름을 잘 따라 오셨다면 popBack도 이해하기 쉬울것이라 생각합니다.
가장 먼저 예외처리를 해야죠 m_used가 0이면 데이터가 아무것도 들어있지 않은 배열이기 때문에 return 합니다.
일단 m_used를 1 줄여줍니다.
그리고 푸시백에서와 마찬가지로 temp 임시 배열을 만들어주고, m_array의 데이터를 복사해줍니다. 앞서 m_used를 1 줄인 이유는 마지막 방은 복사하지 않기 위해서 1을 줄이고 m_used만큼 복사했습니다.
아래는 푸시백과 마찬가지로 새로 만들어서 옮기고 임시배열을 지우는 순입니다. 이해가 잘 되셨나요?
1 2 3 4 | int dynamicArray::operator[](int index) { return this->m_array[index]; } | cs |
아래는 전체 소스코드 올려드리겠습니다.
<dynamicArray.h>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #pragma once #include <stdio.h> class dynamicArray { private: int* m_array; int m_size; int m_used; public: dynamicArray(); dynamicArray(int size); ~dynamicArray(); void popBack(); void pushBack(int data); void print(); int &operator[](int index); }; | cs |
<dynamicArray.cpp>
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 69 70 71 72 73 74 75 76 77 78 79 80 81 | #include "dynamicArray.h" dynamicArray::dynamicArray() : m_size(1), m_used(0) { m_array = new int[m_size]; } dynamicArray::dynamicArray(int size) : m_size(size), m_used(0) { m_array = new int[m_size]; } dynamicArray::~dynamicArray() { delete[] m_array; } void dynamicArray::popBack() { if (m_used == 0) return; m_used--; int* temp = new int[m_used]; for (int i = 0; i < m_used; i++) temp[i] = m_array[i]; delete[] m_array; m_array = new int[m_size]; for (int i = 0; i < m_used; i++) temp[i] = m_array[i]; delete[] temp; return; } void dynamicArray::pushBack(int data) { if (m_size > m_used) { m_array[m_used] = data; m_used++; return; } int* temp = new int[m_size]; for (int i = 0; i < m_used; i++) temp[i] = m_array[i]; delete[] m_array; m_size *= 2; m_array = new int[m_size]; for (int i = 0; i < m_used; i++) m_array[i] = temp[i]; m_array[m_used] = data; m_used++; delete[] temp; return; } void dynamicArray::print() { for(int i=0; i<this->m_used; i++) printf("%d ",this->m_array[i]); printf("\n"); } int& dynamicArray::operator[](int index) { return this->m_array[index]; } | cs |
'C,C++' 카테고리의 다른 글
C/C++ : 클래스(class)의 개념 (1) | 2016.04.11 |
---|---|
C/C++ : 구조체(struct)의 개념 (1) | 2016.04.11 |
자료구조 : 자료구조란? (Data Structure) (7) | 2016.03.29 |
C++ : 연산자 오버로딩(Operator overloading) (0) | 2016.03.29 |
정렬(Sort) : 빠른정렬, 퀵 소트(Quick Sort) (0) | 2016.03.29 |
- Total
- Today
- Yesterday
- 프로세스
- C++
- 터미널
- 데이터베이스
- C/C++
- 티그널
- C
- 클라이언트
- 안드로이드
- 라즈베리파이
- 파일
- 정렬
- 리눅스
- 쓰레드
- 유즈케이스
- 파이썬예제
- UML
- 소켓
- 악보
- socket
- 액터
- 디렉터리
- 클래스
- 자료구조
- 티라노 시그널
- Sort
- MFC
- 파이썬
- 소켓 프로그래밍
- 스레드
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |