3. Template
자료형은 다르지만 내부 작동은 비슷한 클래스나 함수들을 여러 번 작성하지 않고 한 번만 작성할 수 있게 해주는 기능
int min( int a, int b )
{
return ( a < b ) ? a : b;
}
만약 위와 같은 함수가 있을 때,
자료형이 float인 두 변수 중에서 작은 값을 얻으려면
float min( float a, float b )
{
return ( a < b ) ? a : b;
}
float형을 위한 함수를 오버로딩 해야 한다.
그런데 두 함수의 자료형을 제외하면 똑같은 함수이다.
이럴 때 작업을 간단하게 만들어 주는 것이 템플릿 기능
template <class T>
T min ( T a, T b )
{
return ( a < b ) ? a : b;
}
여기서 template라는 것은 이 함수가 template 함수라는
뜻이고, <class T>는 T라는 자료형을 이 함수에서 사용하겠
다는 것을 의미한다.
여기서의 T는 a와 b의 자료형이 무엇인지 지금은 알 수 없
지만 함수가 호출될 때 a와 b의 자료형을 T라고 하겠다는
뜻이다.
그래서 min(a, b)하면 a, b의 자료형에 상관없이 더 작은
값이 리턴된다.
4. 앞에서 본 것은 템플릿을 이용해서 함수를 만들었으므로 템플릿 함수라고 한다.
그리고 같은 기능을 클래스에도 적용시킬 수 있는데, 이 경우를 템플릿 클래스라고 한다.
template <class T>
class A
{
T m_t;
public:
A(T t): m_t(t) {}
void f(T t);
};
위의 예제 코드에서 알 수 있듯이 템플릿 함수와 거의 동일한
방식으로 사용할 수 있다. 다만 템플릿 함수에서는 <class T>로
정의한 자료형을 자동적으로 인식한 반면에 템플릿 클래스는
클래스를 생성할 때는 아래와 같이 자료형을 명시해줘야 하는
차이점이 있다.
A<int> a(10);
예시와 같인 자료형을 int로 선언하면 생성되는 class A는
다음과 동일하다.
class A
{
int m_t;
public:
A(int t): m_t(t) {}
void f(int t);
};
이때 < > 안에 들어갈 수 있는 자료형은 int나 float와 같은
기본 자료형은 물론이고, 프로그래머가 새로 정의한 클래스
나 포인터형도 가능하다.
5. 앞의 예제를 응용해서 좀 더 다양한 템플릿 클래스를 만들 수 있다.
template <class A, class B, int MAX>
class TwoArray
{
// blah blah
A arr1[MAX];
B arr2[MAX];
// blah blah
};
위와 같이 < > 안에 다양한 조건을 명시할 수도 있다.
예를 들어서 앞의 TwoArray라는 클래스를 다음과 같이 생
성하면
TwoArray<int, char, 10> a;
class A에는 int가, class B에는 char가, int MAX에는 10
이라는 값이 할당되어서
a라는 객체 안에는
Int arr1[10]
char arr2[10]
가 생성된다.
6. 신기한 기능인만큼 템플릿에는 몇 가지 특징이 있다.
1. <class T> 대신에 <typename T>를 쓸 수도 있다. 둘은 동일하다.
2. Template은 런타임에 생성되는 것이 아니라 컴파일할 때 만들어진다.
그래서 아주 많이 사용하면 컴파일이 오래 걸린다. (하지만 별로 중요하지는 않다.)
3. 중요한 것은 template function은 항상 헤더 파일에 놓아야 한다는 것이다.
그 이유는 template function은 함수를 만드는 방법을 선언하는 것이기 때문이다.
그리고 만약 template function에서 호출하는 함수가 있다면, 그 함수 역시 헤더 파일에 정의되
어 있어야 한다.
7. STL
일반적으로 사용하는 기능들을 앞에서 살펴본 template 기능을 이용해서 미리 만들어 놓은 것
종류에는 STL Containers, Iterators, Algorithms, Allocators, Function Object가 있다.
STL Containers
자료구조라고 생각하면 편하다.
사용법들이 비슷하니 linked list를 통해 살펴보자.
// 사용하기 위해서는 라이브러리를 불러와야 된다
#include <list>
// 하나 생성하자
// template에서 본 문법이 그대로 적용된다.
// 생성한 리스트가 저장할 데이터 타입을 < > 안에 적어주면 된다.
std::list<int> intList;
// 리스트에 element를 추가해보자
// 여기서 사용한 push_back()은 리스트의 맨 뒤에 자료를 추가하는 것
intList.push_back(5);
// 그럼 이제 추가된 값들 중에 5를 저장하고 있는 노드를 지워보자
intList.remove(5);
8. 그 외에도 STL에는 다양한 멤버함수들이 있다. list를 예로 들면
assign // 기존에 있던 elements를 삭제하고 새로운 elements로 대체
list::clear // 리스트의 모든 elements 광역 삭제
empty // 리스트가 비어있는지 확인
max_size // 리스트의 최대 크기 반환
get_allocator // 리스트를 생성하는데 사용된 allocator를 복사해서 반환
resize // 리스트의 크기를 새로 지정
(더 길어지면 길어진 자리는 기본값들로 채워지고, 더 짧아지면 짧아진 길이보다 뒤에 있던 elements는 지워짐)
reverse // 리스트의 elements의 순서를 뒤집는다
size // 지금 리스트의 크기 반환
sort // 주어진 조건에 따라서 elements를 정렬
splice // 리스트에서 삭제한 element를 대상이 되는 리스트에 삽입
swap // 두 리스트의 elements를 서로 바꾼다
unique // 리스트에서 중복된 값을 가지거나 주어진 조건에 만족하는 지는 elements를 삭제
merge // 지정된 리스트의 elements를 대상이 되는 리스트로 복사하고 조건에 따라서 새로 정렬
9. front // 리스트의 첫 번째 element에 대한 reference 를 반환
back // 리스트의 마지막 element에 대한 reference 를 반환
begin // 리스트의 첫 번째 element에 대한 iterator를 반환
list::cbegin // 리스트의 첫 번째 element에 대한 const iterator를 반환
end // 리스트의 마지막 element에 대한 iterator를 반환
list::cend // 리스트의 마지막 element에 대한 const iterator를 반환
rbegin // 리스트의 역순에서 첫 번째 element에 대한 iterator를 반환
list::crbegin // 리스트의 역순에서 첫 번째 element에 대한 const iterator를 반환
rend // 리스트의 역순에서 마지막 element에 대한 iterator를 반환
list::crend // 리스트의 역순에서 마지막 element에 대한 const iterator를 반환
그 외에도 STL에는 다양한 멤버함수들이 있다. list를 예로 들면
10. list::emplace // 특정한 위치에 element 삽입
list::emplace_back // 리스트의 맨 뒤에 elements 추가
list::emplace_front // 리스트의 맨 앞에 elements 추가
insert // 리스트의 특정한 위치에 하나 혹은 다수의 element를 삽입
push_back // 리스트의 맨 뒤에 element 추가
push_front // 리스트의 맨 앞에 element 추가
erase // 리스트의 특정한 위치에 있는 element 하나 혹은 다수를 삭제
pop_back // 리스트의 맨 뒤 element 삭제
pop_front // 리스트의 맨 앞 element 삭제
remove // 입력한 값을 만족하는 elements 삭제
remove_if // 주어진 조건에 만족하는 elements 삭제
// operator
= // 리스트의 모든 element를 복사
그 외에도 STL에는 다양한 멤버함수들이 있다. list를 예로 들면
11. vector // 동적인 배열로써 원소의 개수를 동적으로 조절할 수 있다
deque // 접근시간은 array, 추가 삭제 시간은 linked list인 자료구조
map // key를 통해서 value에 접근하는 자료구조, key와 value 모두 데이터 타입을 지정할 수 있다
***관련 msdn 페이지
http://msdn.microsoft.com/en-us/library/vstudio/1fe2x6kt(v=vs.100).aspx
자주 쓰이는 STL container
12. Algorithms
말그대로 알고리듬으로써 정렬, 찾기, 순서 바꾸기 등의 기능을 제공한다.
사용 방법은 STL container와 비슷하지만 개별 알고리듬을 include하지 않고 한번에 전체를 include한다.
// 다음과 같이 include해주고
#include <algorithm>
// 이렇게 사용하면 된다.
std::sort(first, last);
여기서 사용된 sort()는 first에서 last까지의 데이터가 오름차순으로 정렬되는데,
평균적인 시간 복잡도는 N = last – first일 때, O(N log N)이다.
주의할 점은 sort()는 stable한 알고리듬이 아니므로 stable한 정렬 결과를 원한다면 stable_sort()를 사용해야 한다.
이와 같이 각각의 알고리듬의 특징은 msdn에서 관련 정보를 찾을 수 있다.
13. find() // 선형 검색 알고리즘
replace() // 특정한 값을 갖는 element를 찾아서 입력한 값으로 교체
reverse() // 원소들의 순서를 반대로 뒤집는다
binary_search() // 원소들이 정렬되어 있을 때 사용할 수 있으며, 좀 더 빨리 원하는 데이터를 찾을 수 있다
***관련 msdn 페이지
http://msdn.microsoft.com/en-us/library/vstudio/wh15hsex(v=vs.100).aspx
자주 쓰이는 Algorithms