[C++] std::move 와 std::forward
[C++] std::move 와 std::forward
2022.04.09언제 std::move를 사용해야 하는지, 언제 std::forward를 사용해야 하는지 알아보는 시간을 가져보도록 하겠습니다. 1. std::move std::move의 경우 형변환 작업을 수행합니다. 받은 param에 대해 R-value reference를 반환합니다.예를 들면 이런 식 입니다. #include void Function(int&& Arg) { std::cout
[C++] STL Custom Allocator 사용
[C++] STL Custom Allocator 사용
2022.04.08Custom Allocator를 사용해서 STL Container들이 사용할 버퍼를 공급할 수 있습니다. STL Cotainer는 Element가 들어갈 Container Buffer의 할당시 템플릿으로 구현된 Allocator 클래스를 사용합니다. STL에서의 할당 동작시의 힙 파편화가 우려되는 상황이라면, 커스텀된 Allocator 클래스를 우리가 직접 구현하고, 미리 구현해둔 메모리풀로 이어지게 해서 통제할 수 있습니다. 우선 STL Cotainer의 할당시 동작의 이해를 위해서 아주 간단한 allocator 클래스를 구현하겠습니다. 할당시 동작할 내부 구현을 바꿔서 프로젝트 상황에 맞게 사용하시면 되겠습니다. 물론 말씀드렸듯이 STL Cotainer는 템플릿을 통한 호출을 하기 때문에 함수의 시그..
[C++] C++ 11 mutable
[C++] C++ 11 mutable
2022.03.28C++11 에 mutable keyword가 추가 되었다. 아래의 간단한 코드를 보도록 하자. 너무 간단하다. #include class Entity { private: int A = 10; mutable int B = 20; int C = 30; public: Entity() {} virtual ~Entity() {} void Function() const { //A = 20; //컴파일 에러 함수 선언에 const가 붙었다. B = 30; //Okay. //B에는 mutable 키워드가 붙었음으로 const가 붙은 함수에서도 B값에 대한 수정이 허용된다. } }; mutable은 멤버 변수 혹은 람다에서 사용이 가능하다. int main() { mutable int A = 10; //무의미하다. //..
[C++] C++11 override, final
[C++] C++11 override, final
2022.03.28C++11 에 override 와 final 키워드가 추가되었다. 아래의 코드를 보도록 하자. 1. override #include class EntityBase { public: virtual void Print() { std::cout
[C++] new[] , delete[] 오버로딩시 주의 사항.
[C++] new[] , delete[] 오버로딩시 주의 사항.
2022.03.281. 연산자 vs CRT 함수 동적할당이라는 단어에 대해서 잘 생각해보아야 한다.우리가 힙이라고 부르는 것은 풀어쓴다면 다음과 같다. "스택 프레임과 별개로 프로그래머가 내킬때 해제할 물리메모리" 동적 할당은 OS자원에 대한 요청이다. OS에게 "스택 프레임과 별개로 프로그래머가 내킬때 해제할 물리메모리" 에 대한 요청을 한다. OS에게 물리메모리에 사용에 대한 허락을 받으면,우리는 힙에 할당되었다고 이야기 하는 것이다. 핵심은 new와 delete는 연산자이고 malloc 과 free는 CRT 함수이다. new와 delete가 연산자라는 말은, 어디까지나 C++ 컴파일러가 인식하는 키워드 라는 것이다. 컴파일러는 new와 delete를 발견하면 일련의 기계어 동작으로 해석해낸다. 그리고 그 일련의 기계..
[C++] const lvalue reference, rvalue reference
[C++] const lvalue reference, rvalue reference
2022.03.23C++11에 std::move 그리고 std::forward 가 추가 되었다. 우선 lvalue와 rvalue 의 개념을 이해해야 제대로 사용할 수 있을 것 같아 정리하기로 한다. 1. lvalue lvalue는 이름이 있는 값이다. 그러니까, C++ 코드에서 변수명을 정한 값이 바로 lvalue이다. 글로 표현할수록 오개념이 생길 수 있다. 아래의 아주 간단한 코드를 보도록 하자. int IamInt = 10; //IamInt는 lvalue이다. //이름에서 알 수 있듯 대입시에 좌측에 위치한다. //IamInt 라는 이름을 가졌기 때문에, 이 곳으로의 값의 복사는 //위 처럼 간단하게 가능하다. 아주 쉽다. 우선은 우리가 아는 variable 의 개념이 lvalue라고 이해하자. 하나의 예시를 더 보..
[C++] C++11 constexpr
[C++] C++11 constexpr
2022.03.20상수는 어떤 특징을 가지는가? 컴파일타임에 약속되고, 절대 변하지 않는다는 보장이 있어야 한다. 이러한 점을 컴파일러에게 알려주는 키워드가 바로 constexpr이다. 기존 const가 있는데 왜 constexpr이 따로 생겼나요? 아래의 예시를 보도록하자. 1. const #include int main() { //const std::size_t Size = 10; //int Array[Size]; //가능. //초기화 이후 바뀌지 않는다. //그렇다면 만약 ? const std::size_t Size = 10; size_t* Casted = const_cast(&Size); *Casted = 50; int Array[Size]; std::cout
[C++] 스마트 포인터 unique_ptr, shared_ptr, weak_ptr
[C++] 스마트 포인터 unique_ptr, shared_ptr, weak_ptr
2022.03.19C+11에 템플릿으로 구현된 세가지의 스마트포인터 unique_ptr, shared_ptr, weak_ptr가 추가되었다. 아마도 가장 많이 사용하고 있지 않은가 싶다. 특히나 C++로 게임을 만드려고 한다면 객체의 생명주기 관리를 위해 잘 알아두는 것이 좋겠다. 1. unique_ptr 대입 연산자를 막아버렸다. 의도는 명확하다. 다른곳에서 참조하지 말라는 의미다. 물론 get을 호출하면 raw pointer를 얻을 수 있다. 그럼 사실상 무의미 해진다. #include #include class MyInstance { public: void operator delete(void* pAddress) { std::cout
[C++] Type Casting 연산자 정리 static, dynamic,reinterpret, const
[C++] Type Casting 연산자 정리 static, dynamic,reinterpret, const
2022.03.17모든 데이터는 바이너리 데이터로 이루어진다. 포인터에 대한 형변환은 언어에게 그냥 해당 주소안에 있는 데이터를 이 형태로 취급해라 라는 정도이다. 그래서 어떤 어드레스에 대해 역참조를 하면 포인터의 형태가 int* 이면 4byte를 읽어들이고, long long 형이면 8byte를 읽어 들이는 것 뿐이다. 다만 이런 캐스트 연산자를 사용하는 이유는 언어 차원에서 뭔가 의도한건 아닌거 같은데? 정도를 잡아내게끔 할때이다. 1. static_cast int* From = new int; void* To = static_cast(From); //No. int* From = new int; void* To = static_cast(From); //No. long long* From = new long long;..
[C++] C++ 11 Argument로 전달된 정적 배열의 크기
[C++] C++ 11 Argument로 전달된 정적 배열의 크기
2022.03.05보통 버퍼를 Argument로 전달하면 char* 형태로 전달한 다음 인자가 하나 더 들어간다. size_t 타입으로 cbSize같은 형태로 배열의 크기를 전달하곤 하는데, 템플릿을 사용할때에 피곤한 일이 발생한다. 여러개의 오버로딩된 함수를 템플릿 함수 내 에서 호출한다고 하면, 인자의 개수가 같은 쪽이 훨씬 더 구현하기 깔끔하기 때문이다. 이렇게 배열의 크기가 인자의 개수를 통일하지 못하게 막고 있다면, C++11 부터 추가된 Type Inference를 이용하면 간단하게 해결할 수 있다. 아래의 예시를 보도록 하자. 간단하다. template void ArraySize(T (&buffer)[Size]) { std::cout
[C++] C++11 Parameter Pack 사용하기
[C++] C++11 Parameter Pack 사용하기
2022.03.05C++11 부터 Parameter Pack 을 사용할 수 있다. 아래의 간단한 예시를 보도록 하자. //Argument가 1개 일때. template void ParamPackFunction(const T& Last) { std::cout
[C++] C++ new 연산자 오버로딩을 이용한 메모리 풀 만들기
[C++] C++ new 연산자 오버로딩을 이용한 메모리 풀 만들기
2022.01.27메모리풀을 만들때에 AllocInstance나 ReleaseInstance같은 정적함수들을 구현해서 객체 생성시에 사용하기도 한다.물론 좋은 방법이지만, 템플릿을 사용할때에 귀찮은 일이 발생한다. 템플릿 함수 내에서 풀링을 사용하려면 강제로 형변환을 해야하며, AllocInstance 와 ReleaseInstance 사용하는 경우와 그렇지 않은 경우를 두개를 만들어야 한다. 귀찮은 여러 작업이 동반된다는 것은 다시말해 그만큼 타입 특정에 대해서 실수할 위험성이 항상 존재한다는 이야기이기도 하다. 템플릿으로 인터페이스를 만들고 new 와 delete를 오버로딩하는 방법을 사용하면, 이런 귀찮음과 위험을 해결할 수 있다. new와 delete는 어디까지나 연산자이기 때문이다. 별도로 Initialize 같은..