C++

    C++ 자기 자신 참조 (this)

    아래 코드를 살펴보면 Set 함수에서 멤버 변수 val에 파라미터로 넘어오는 값을 대입하고자 하는데 공교롭게도 val을 파라미터로 넘어오는 값으로 인식한다 val은 초기화가 안됐으므로 쓰레기값이 출력될거다. #include using namespace std; class Parent { int val; public: void Set(int val) { val = val; } int Get() const { return val; } }; int main() { Parent parent; parent.Set(10); cout

    C++ 추상 클래스 / 순수 가상 함수 (Pure Virtual Function)

    순수 가상함수란 선언(declaration)만 있고 구현(definition)이 없는 가상 함수다. virtual void Func() = 0; 추상 클래스 위와 같은 순수 가상함수를 하나라도 가지고 있는 클래스를 추상클래스(abstract class)라고 한다. 추상 클래스는 객체를 생성할 수 없다. 추상 클래스는 멤버 함수의 원형만을 정의하고 그 구현은 자식 클래스에서 하게 된다. 추상 클래스를 상속받는 자식 클래스는 반드시 순수 가상함수를 오버라이딩 하여 재정의 해야만 한다. 그렇지 않다면 아래 그림과 같이 컴파일 오류가 난다. 이렇게 추상클래스를 활용하면 파생클래스에서 순수 가상함수를 재정의 하게끔 강제할 수 있다. #include using namespace std; class Parent { ..

    C++ 클래스 접근 제한자 (Access Modifier)

    public, private, protected 바로 이 3가지이고 쓰여지는 이유는 객체지향 프로그래밍의 중요한 개념 중 하나는 데이터 숨김(은닉) 때문이다. 클래스 내에 멤버에 대한 접근 제한자를 두지 않으면 기본적으로 private이다. 구조체 멤버에 대한 기본적인 접근 제한자는 public이다. friend 키워드는 private와 protected의 원칙을 깨트림으로서 코드의 직관성과 흐름 파악을 복잡하게하는 goto같은 존재이다. friend 관련 글 참고 public public으로 선언된 데이터 멤버 및 멤버함수는 . 연산자를 사용하여 프로그램의 아무곳에서나 액세스 할 수 있다. private 클래스 멤버를 private으로 선언하면 해당 멤버는 오직 클래스 내부에서 접근할 수 있다, 외부의..

    C++ 원자적 연산 (atomic)

    뮤텍스를 통해서 전역 변수를 동기화하여 하나씩 증가시킬 수 있다. 그러나 뮤텍스와 같은 lock을 이용하여 개발하는 경우, 사용자가 잘못 사용할 때 교착 상태와 같은 문제를 야기시킬 수 있다. C++11에서는 atomic을 이용하여 뮤텍스와 같이 lock, unlock을 사용하지 않고 값을 증가시키거나 값을 감소시킬 수 있는 기능을 제공하고 있다. atomic : atomic 변수를 선언할 수 있는 데이터형. fetch_add : atomic의 멤버 함수로, 값을 증가시키는 함수. fetch_sub : atomic의 멤버 함수로, 값을 감소시키는 함수. atomic으로 설정된 변수에는 초기에만 값을 대입할 수 있다. 그 이외에는 대입이 불가합니다. 대신 값을 증가, 감소 시키는 역할만 수행한다. 그 이유..

    C++ 스마트 포인터 (Smart Pointer)

    C++ 프로그램에서 new 키워드를 사용하여 동적으로 할당받은 메모리는, 반드시 delete 키워드를 사용하여 해제해야 하는데, 만약 해제하지 않고 넘어갈 경우에 메모리 누수 (Memory Leak) 문제가 발생해서 프로그램의 안정성을 보장받을 수 없게 된다. 스마트 포인터는 클래스 템플릿으로서 사용이 끝난 메모리를 자동으로 해제해주어 메모리 누수 문제가 일어나지 않도록 해준다. 동작하는 방법은 기본 포인터 (Raw Pointer)가 실제 메모리를 가리키도록 초기화한 후에, 기본 포인터를 스마트 포인터에 대입하여 사용된다. 스마트 포인터의 종류 C++ 11 표준 이전에도 auto_ptr 이라는 스마트 포인터로 작업을 처리했었는데, 현재 모던 C++ 이라 불리우는 C++ 11 이상의 표준에 대해서는 aut..

    C++ 바이트 패딩 (Byte Padding)

    왜 컴파일러는 구조체의 메모리를 정렬해 놓을까? 적은 수의 컴파일러는 구조체의 필드를 메모리에 위치시킬 때, 중간 빈 공간 없이 쭉 이어서 할당한다. 하지만 대부분의 컴파일러는 성능 향상을 위해 cpu가 접근하기 쉬운 위치에 필드를 배치하는 데 이를 구조체 패딩이라고 한다. 그리고 중간 빈 공간에 들어간 것을 패딩 비트라고 한다. 참고로 os 32bit 환경에서는 4byte packing 방식이 빠르고 os 64bit 환경에서는 8byte packing 방식이 빠르다고 한다. 왜 빠를까? 패딩 비트가 없을 경우 어떤 일이 일어나는지 생각해보자. cpu는 메모리를 읽어올 때 한 번에 32bit os : 4byte 혹은 64bit os : 8byte를 읽어온다. class Test { char _c1; //..

    [Unreal] C++ 버전 변경(C++ 20기능 사용) 방법과 모듈

    언리얼에선 디버그 속성 통해 전체 .sln 파일에 대해 언어를 지정 할 수가 없다. UE 5 기준 전체 언리얼 모듈들은 C++ 17버전으로 작성 되어있다, 따라서 20 버전으로 업그레이드 한 후 참조할 때 에러가 날 수 있다. 각 모듈 Build.cs 파일 내에 // CppStandardVersion.Latest 즉 최신 버전 설정 시 17 버전으로 설정 됨. CppStandard = CppStandardVersion.Cpp17; // C++ 20 기능 사용하고자 할 때 아래와 같이 작성하면 된다. CppStandard = CppStandardVersion.Cpp20; 아래는 현재 사용하고 있는 직접 구현한 모듈들이다. Objects 같은 경우엔 탄알(파티클 이펙트) Niagara System을 사용해야..

    C++ 참조 대상 수 (Reference Counting)

    Reference Counting은 객체의 소유권 관리( = 라이프 사이클 )의 방법 중 하나로 객체를 참조(포인팅) 하고 있는 횟수를 추적하여 그 횟수가 0이 되면 메모리에서 해제(소멸)한다. 대부분의 Managed Language (python, c#, swift등 메모리 관리를 직접 하지 않는 언어 ) 에서 널리 사용되고 있다. 장점 - 메모리를 직접 해제하는 번거로움이 사라진다. - 객체의 소유권을 공유할 수 있다 - 객체 관리 매커니즘이 비교적 단순해서 빠르다. (Garbage Collection) 단점 - 순환 참조 문제가 있다. c++ 에서의 구현방식에는 크게 두가지가 있다. Intrusive Reference Counting (침습성 참조 카운팅) - 객체에 대한 참조 카운트가 "내장" 되..

    C++ 순환 참조 (Circular Dependency) & 데드락

    순환 참조 문제는 비단 Reference Counting 뿐만이 아니라 다양한 영역에서 이를 피하는것이 매우 중요하다. 설계적 관점에서, 서로 참조를 하는 두 객체가 있다면 의존 관계가 양방향이 되고 의존성(Dependency)이 커지기 때문에 코드 관리에 어려움이 생긴다. 멀티 스레드( or 프로세스 ) 환경에서는 Resource를 점유한 상태로 새 Resource의 요청이 "순환"하는 경우 교착 상태(Dead Lock)에 빠지게 된다. class ObjectA { public: ObjectA() { std::cout

    멀티 스레드 (Multi Thread) 소스코드

    병렬처리 기법중 하나로 cpu안에 있는 여러개의 코어를 이용해서 더욱더 빠른 연산을 하게하는 기법이다. #include #include #include #include using namespace std; // 임계 영역 mutex mtx; //mutual exclusion int main() { // 여러가지 일을 동시에 처리 // cout이 깨지지않게 실행시키기 위해서 // mutex를 이용해 cout을 lock시키고 다 실행되면 // unlock하는 식으로 이용한다. auto work_func = [](const string& name) { for (int i = 0; i < 5; i++) { this_thread::sleep_for(chrono::milliseconds(100)); mtx.lock..