[CPP] 다이렉트 들어가기 전 새로운 문법

라멘커비·2024년 3월 18일
0

WinApi

목록 보기
32/32

fmodL_vc를 디버그 모드일 때 쓰는 건 출력 창에 FMOD가 로그를 띄워주기 때문이다. Release 모드일 때는 로그 출력 필요 없고 최적화된 fmod_vc 사용.

디버그 모드일 때는 A코드만, 릴리즈 모드일 때는 B코드만 실행되어야 할 때 사용하는 것이 ifdef이다. 다른 조건쪽의 코드는 아예 빌드에서 빠지게 된다.

ifdef

define문은 치환 이외에도 "전처리문 ~를 정의했다." 라는 의미가 있다.

#ifdef xxx 디파인을 선언했다면
#else 선언 안 했다면
#endif 여기가 조건의 마지막
//#define DEBUG 
// ↑이건 내가 꼭 해야하는 게 아니고 각 빌드 설정마다 비쥬얼 스튜디오에서 소매넣기(?) 되어있음 

#ifdef _DEBUG
#pragma comment(lib, "fmodL_vc.lib")
#else
#pragma comment(lib, "fmod_vc.lib")
#endif


  • 다이렉트 넘어가기 전에 배울 것들
    : std::shared_ptr, thread를 배울 것임

  • 면접에 자주 나오는 std관련 클래스들
    초중요. 함수 다 알고 사용 시의 주의사항이나 불리한 점을 알아야 한다.

std::vector
std::list
std::map
std::string & std::string_view

std::shared_ptr

std::functional

std::queue
std::stack

std::shared_ptr 개요

std에 속한 stl 중 한 클래스. (stl != 자료구조)

template<typename PointerType>
std::shared_ptr<PointerType>

포인터를 2개 또는 그 이상 나눠서 가졌을 때 잘못 Destroy하면 댕글링이됨. (댕글링이 위험한 이유는 메모리 크러쉬로 인해 fatal 에러. 흔히 말해 프로그램 터지기 때문.)
=> 이걸 어느정도 해결하지 위해서 등장한 게 shared_ptr

이걸 사용하면 문제가 되는 부분이 있음. 이제 안 지워지는 지를 모름.

  • 레퍼런스 카운트 방식
    클래스를 포인터 대신 씀. 그 클래스에서는 포인터를 가지면서 포인터를 가리키는 곳의 개수를 갖고 있음. 소멸될 때 레퍼런스 카운트가 줄어듦, 이 참조하는 포인터 수가 0 이하가 되기 전에는 메모리를 지우지 않음.
#include <iostream>

class Test
{
public:
    Test()
    {
        int a = 0;
    }

    ~Test()
    {
        int a = 0;
    }
};

class TestPtr
{
public:
    int* RefCount = nullptr;
    Test* Ptr = nullptr;

    void DecRefCount()
    {
        int& Ref = *RefCount;
        --Ref;
    }

    void AddRefCount()
    {
        int& Ref = *RefCount;
        ++Ref;
    }

public:
    TestPtr(Test* _Ptr)
        : Ptr(_Ptr)
    {
        if (nullptr == RefCount)
        {
            RefCount = new int();
            *RefCount = 1;
        }
    }

    // 복사 생성자
    TestPtr(const TestPtr& _OtherPtr)
        : Ptr(_OtherPtr.Ptr)
        , RefCount(_OtherPtr.RefCount)
    {
        AddRefCount();
    }



    ~TestPtr()
    {
        DecRefCount();

        if (0 >= *RefCount)
        {
            delete RefCount;
            delete Ptr;
        }
        
    }
};

TestPtr Test_make_shared()
{
    Test* NewTestPtr = new Test();

    return TestPtr(NewTestPtr);
}
TestPtr Ptr0 = Test_make_shared();
TestPtr Ptr1 = Ptr0;

근데 이제 안 지워졌는지를 모르게 됨. Destroy를 했는데 안지워지는 경우가 생기는 것임.

  • 순환참조, 왜 릭이 두 개 남는지 생각해보기
    서로 못 지워서 두 개가 남는 건 알겠는데, 왜 32, 32바이트씩 남냐? -> PtrA, PtrB가 순환 참조돼서 서로 못지워짐 -> PtrA의 멤버변수 BPtr 16바이트 + 걔가 가리키는 클래스B의 크기 16바이트 해서 32, PtrB의 멤버변수 APtr 16바이트 + 걔가 가리키는 클래스A 크기 16바이트 => 32 -> 그래서 32바이트씩 두 개 나오는듯!
// 순환 참조
class A
{
public:
    std::shared_ptr<class B> BPtr;
public:
    A()
    {
    }

    ~A()
    {
    }
};

class B
{
public:
    std::shared_ptr<class A> APtr;

public:
    B()
    {
    }

    ~B()
    {
    }
};
    {
        // 순환참조
        std::shared_ptr<A> PtrA = std::make_shared<A>();
        std::shared_ptr<B> PtrB = std::make_shared<B>();
        PtrA->BPtr = PtrB;
        PtrB->APtr = PtrA;
    }
profile
일단 시작해보자

0개의 댓글