본문 바로가기
대외활동/시스템프로그래밍

템플릿 & STL

by hoshi03 2024. 7. 29.

• 함수 중복의 약점

함수 중복은 매개변수 이외의 코드가 중복되어 비효율적이다

 

• 템플릿 선언을 이용한 swap 함수

template<class T>나 template<typename T> 형태로 제네릭 타입을 선언하고 사용한다

#include <iostream>

using namespace std;

template<class T>
void myswap(T& a, T& b) {
	T tmp;
	tmp = a;
	a = b;
	b = tmp;
}

int main() {
	int a = 4, b = 5;
	cout << "a = " << a << " b = " << b << "\n";
	myswap(a, b);
	cout << "a = " << a << " b = " << b << "\n";

	double c = 1.2;
	double d = 0.3;
	cout << "c = " << c << " d = " << d << "\n";
	swap(c, d);
	cout << "c = " << c << " d = " << d << "\n";

}

 

템플릿을 이용하면 재사용성이 증가하지만 포팅에 취약하고 디버깅이 어려워진다

 

• 템플릿 스택 코드

#pragma once
#include <iostream>

using namespace std;

template<class T> 
class MyStack{
	int size;
	T* arr;
	int top = -1;

public:
	MyStack<T>();
	MyStack(int s);
	~MyStack();

	bool pop(T* x);
	bool push(T n);
	bool isEmpty();
	int getSize();
	int setSize(int n);
	int getTop();
	int getData();

	void printAll();
};

template<class T>
MyStack<T>::MyStack() {
	cout << "기본 스택 생성" << '\n';
	size = 10;
	arr = new T[size];
}

template<class T>
MyStack<T> ::MyStack(int s) {
	cout << "크기가 " << s << "인 스택 생성" << '\n';
	size = s;
	arr = new T[size];
}

template<class T>
MyStack<T>::~MyStack() {
	cout << "스택 소멸" << '\n';
	delete[] arr;
}

template<class T>
bool MyStack<T>::pop(T* x) {
	if (top == -1) return false;
	*x = (T)arr[top];
	top--;
	return true;
}

template<class T>
bool MyStack<T>::push(T n) {
	if (getTop() >= getSize()) setSize(size * 2);
	arr[++top] = (T)n;
	return true;
}

template<class T>
int MyStack<T>::getSize() {
	return size;
}

template<class T>
int MyStack<T>::setSize(int n) {

	T* tmp = new T[n];

	if (n < getSize()) {
		copy(arr, arr + n, tmp);
		if (getTop() >= n) top = n - 1;
	}
	else copy(arr, arr + getSize(), tmp);

	delete[] arr;
	arr = tmp;
	size = n;

	return size;
}

template<class T>
int MyStack<T>::getTop() {
	return top;
}

template<class T>
int MyStack<T>::getData() {
	return (T)arr[top];
}

template<class T>
bool MyStack<T>::isEmpty() {
	if (top == -1) return true;
	return false;
}

template<class T>
void MyStack<T>::printAll() { //일괄출력
	while (!isEmpty())
	{
		T tmp ;
		pop(&tmp);
		cout << tmp << " ";
	}
	cout << '\n';
}

 

• auto를 이용한 이터레이터 순회

 

순회할 데이터 타입은 Employee*이 담긴 벡터

vector<Employee*> empList;

 

auto 키워드를 통해서 이터레이터를 쉽게 선언할 수 있다

for (auto it = empList.begin(); it != empList.end(); ++it) {
        res += (*it)->getPay();
    }

 

• map 사용법

 

키, 값 쌍으로 이루어진 map

pair를 이용해 값을 넣고 map[키] = 값 형태로 가져온다

int main() {
	std::map<string, string> dic;
	dic.insert(make_pair("love", "사랑"));
	dic.insert(make_pair("lover", "사랑하는 사람"));
	dic.insert(make_pair("loved", "사랑했었다.."));

	cout << dic.size() << '\n';

	string tmp;
	while (true)
	{
		getline(cin, tmp);
		if (tmp == "exit") break;

		if (dic.find(tmp) == dic.end()) cout << "없음" << '\n';
		else cout << dic[tmp] << '\n';
	}

	cout << "종료" << '\n';
}

 

• sort

sort(arr.begin(), arr.end()); //원형
sort(arr.begin(), arr.end(), greater<>()); //내림차순

// 사용자 정의 정렬, compare를 사용자가 만들어준다
bool comparator(int a, int b) {
	return a > b;
}

// 사용자 정의 정렬
sort(arr.begin(), arr.end(), compare);

 

• count & count_if

 

count : first 부터 last까지 특정 값이 몇개나 있는지를 세는 함수

int myints[] = {10, 20, 30, 30, 20, 10, 10, 20};  // 8 elements
int mycount = std::count(myints, myints + 8, 10);
std::cout << "10 은 " << mycount << " 번 등장합니다.\n";

 

count_if : first부터 last까지를 bool 함수에 넣어서 참을 리턴하는게 몇개인지를 세는 함수

func(first) 부터 func(last)까지 값 중 조건에 맞는게 몇개나 있는지를 찾는다 

bool isOdd(int i) { return (i % 2) == 1; }

int main() {
	vector<int> arr = {1, 2, 3, 4, 5, 1, 3, 7};
	int res = count_if(arr.begin(), arr.end(), isOdd);
	cout << res << '\n';
}

 

• Lvalue Rvalue <- 조사해보기

 

• move 메서드

 

객체를 다른 객체로 '이동'한다

복사하지 않고 효율적으로 이동시키고, 원본에는 더 이상 데이터가 남아있지 않게 된다

std::vector<std::string> v;
std::string str = "example";
v.push_back(std::move(str));  // str 은 이제 껍데기만 남음
str.back();                   // 정의되지 않은 작업!
str.clear();                  // 다만 clear 자체는 가능하다.

 

std::string foo = "foo-string";
	std::string bar = "bar-string";
	std::vector<std::string> myvector;

	myvector.push_back(foo);                    // copies
	myvector.push_back(std::move(bar));         // moves

	std::cout << "myvector contains:";
	for (std::string& x : myvector) std::cout << ' ' << x;
	std::cout << '\n';

	return 0;