vector 구현해보기!
카테고리: CppStudy
vector 구현해보자!!
container
종류 | 설명 | ex. |
---|---|---|
시퀀스 컨테이너 | 데이터를 선형으로 저장하며, 특별한 제약이나 규칙이 없는 가장 일반적인 컨테이너 |
vector, deque, list, forward_list |
연관 컨테이너 | 데이터를 일정 규칙에 따라 조직화하여 저장하고 관리하는 컨테이너 | set, multiset, map, multimap |
컨테이너 어댑터 | 기존 컨테이너의 인터페이스를 제한하여 만든(기능이 제한되거나 변형된) 컨테이너 | stack, queue, priority_queue |
vector
생성하면 heap 메모리에 생성되며 동적할당됨.
array에 비해 속도적인 측면에서 떨어지지만 편리하다.
template을 사용하기 때문에 데이터 타입을 마음대로 넣을 수 있다.
내부에 iterator 클래스를 가지고 있기 때문에
vector 의 시작부분을 => .begin() , vector 의 끝 부분을 .end() 로 표현할 수 있다.
목표
template 과 iterator 의 개념을 익히자!
CArr.h
template
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# pragma once
template<typename T>
class CArr
{
private:
public:
CArr();
~CArr();
};
template<typename T>
CArr<T>::CArr()
{
}
template<typename T>
CArr<T>::~CArr()
{
}
템플릿 클래스는 모두 헤더파일에서 작성한다.
템플릿 클래스는 클래스가 아니다.
클래스 위에 template<typename T>
와 같이 작성하는데 이를 클래스라고 생각하면 안된다.
클래스를 찍어낼 수 있도록 틀을 만드는 것이다.
만약 .h 파일에 정의하고 .cpp 파일에 구현하게 된다면 Main.cpp 파일에서 오류가 나게 된다.
Main.cpp 가 .h 파일을 코드위 제일 위에서 검사하고 컴파일을 하는데
.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
# pragma once
template<typename T>
class CArr
{
private:
T* m_pData;
int m_iCount;
int m_iMaxCount;
public:
CArr();
~CArr();
};
template<typename T>
CArr<T>::CArr()
: m_pData(nullptr), m_iCount(0), m_iMaxCount(2)
{
m_pData = new T[2];
}
template<typename T>
CArr<T>::~CArr()
{
delete[] m_pData;
}
이 템플릿은 현재 데이터 개수, 맥스 데이터 개수가 필요하고 T* m_pData
가 필요하다.
왜 포인터(주소값)가 필요할까?
그 이유는 container를 배열로 구성하기 때문이다.
우리가 배열을 만들면 arr[0] 은 그 배열의 시작지점이다.
데이터 묶음의 시작주소를 저장해두는 것이다.
템플릿의 생성자에서 new T[2]
로 size 가 2 인 배열을 생성하고 시작 주소값을 m_pData
에 저장한다.
템플릿의 소멸자에서 delete[] m_pData
를 통해서 동적할당된 데이터를 지운다.
동적할당된 데이터가 배열 형식이라면 delete
뒤에 []
를 붙여주어야 한다.
push_back 함수 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 클래스 내부
public:
CArr();
~CArr();
void push_back(const T& _data);
// 클래스 외부
template<typename T>
void CArr<T>::push_back(const T& _data)
{
if(m_iMaxCount <= m_iCount)
{
}
m_pData[m_iCount++] = _data;
}
다음과 같이 push_back 함수를 추가한다.
그리고 Main.cpp 에서 확인해보자.
Main.cpp
1
2
3
4
5
6
7
8
9
10
#include "CArr.h"
#include <iostream>
using namespace std;
int main()
{
CArr<string> V;
V.push_back("zero");
V.push_back("one");
return 0;
}
테스트를 해보면 데이터 대신 시작 주소값을 넣었기에 들어간 데이터를 눈으로 직접 볼 수는 없지만
다음과 같이 카운트가 증가하는 것을 볼 수 있다.
m_iCount 와 m_iMaxCount 가 같아지게 되면 배열이 꽉 찼다는 의미이다.
따라서 다음과 같이 배열을 재할당 해주어야 한다.
이 기능을 가진 함수가 Resize() 함수이다.
다음 글에서 push_back 함수 내의 Resize() 함수부터 작성해보자.
댓글남기기