decltype: 컴파일 시점에 타입을 추론-선언하는 방법
template <typename T, typename U>
void ef (T x, U y)
{
decltype(T*U) tu;
// 이러면 T랑 U를 곱했을 때의 타입으로 선언해준다.
tu a;
}
함수를 선언할 때 리턴타입을 화살표로 정해줄 수 있다.
그러니까 double f1(double, int)일걸
auto f2(double, int) -> double 할 수 있다는 것이다.
여기에 decltype을 적용하면 이런 것도 가능해진다.
auto eff(T t, U u) -> decltype(T*u)
근데 decltype(T*u) eff(T t, U u) 이렇게 직접 하는 건 컴파일 에러 난다
using으로도 template에서 자료형 타입을 정해줄 수 있다.
typedef std::vector<std::string>::iterator itType;을,
using itType = typedef std::vector<std::string> 이렇게 가능
원래 template function을 만들려면,
template <typename T>
r
template <>
void sort<char>(char arr[], int size)
{
// code to implement counting sort
}
lvalue: 프로그램에서 접근할 수 있는 주소값을 가지고 있는 데이터를 의미한다.
rvalue: 임시적 공간이다.
예를 들어 z = x+y 이런 수식이 있다고 했을 때 z에는 주소값이 있어서 이를 직접 가져올 수가 있지만 x+y는 안 된다.
int x = 10;
int& rx = x; // lvalue ref
int&& rrx = 13; // rvalue ref
rvalue Reference는 &&를 통해 만들어낼 수 있고, 이게 생긴 이유는 바로 다음에 설명할 Move Semantics 때문이다.
move semantics를 쓰는 이유는 뭘까?
copy constructor를 쓰면 임시로 데이터를 복사해야 할 때도 방대한 데이터를 모두 복사해야 하기 때문에 메모리 낭비가 일어난다. 따라서 move constructor를 이용해서 데이터의 소유권 자체를 이전한다.
Useless(const Useless &f) 원래 copy constructor는 이렇게 생겼다.
Useless(Useless&& f); 이걸 move constructor라고 한다 (&& 사용)
예를 들어 int n, char* pc의 변수를 가진 class Useless가 있다고 하자
Useless::Useless(Useless &&f)
: n(f.n)
{
pc = f.pc; // 1. 포인터 주소를 복사한다
f.pc = nullptr; // 2. 원래 포인터를 없앤다.
f.n = 0; // 3. 원래 꺼는 초기화 시킨다
}
이제 move constructor가 언제 사용되는지 알아보자
Useless one(10);
Useless two = one; // one은 lvalue이므러 copy constructor 호출됨
Useless three(20);
Useless four(one+three); // one+three는 rvalue이므로 move constructor가 호출된다