C++

[기본] 소멸자의 virtual 키워드에 대해

매운돌 2023. 6. 25. 05:09

기본적으로 C++에서는 소멸자에 virtual 키워드를 붙이는 습관을 들이라는 이야기를 많이 합니다. 왜냐하면 실수로 virtual 키워드를 붙이지 않게되었을 때, 다형성의 형태로 객체들을 관리하게 되면 Memory Leak이 발생할 수 있기 때문입니다. 하지만 해당 Class를 상속하지 않거나 상속하더라도 다형성의 형태로 사용하지 않는다면 virtual 키워드를 붙였을 때 비효율이 발생하게 됩니다. 

 

첫 번째로 코드의 크기가 증가하게 됩니다. 우리는 소멸자에 virtual 키워드 하나 붙였을 뿐이지만, 실제로 상당히 많은 양의 코드가 만들어지게 되게 됩니다. 그리고 이에 따라 바이너리 사이즈가 커지고 해당 소멸자를 수행하는 시간이 길어지게 됩니다.

두 번째로 Class의 메모리 offset 0 부분에 vfptr이라는 가상 함수 테이블 포인터가 생성되게 됩니다. 따라서 필요하지 않는 추가적인 메모리 낭비가 발생하게 됩니다.

 

하지만 Class가 현재 그렇다고 해서 미래에도 상속되지 않거나, 상속되더라도 부모 다형성의 형태로 사용되지 않는다고 보장할 수 없습니다. 따라서 이럴 경우 Base Class의 소멸자에 접근지정자를 protected로 설정하게 되면, Base Class로 Child Class를 관리하다가 delete하게 될 경우 컴파일 에러가 발생하게 되어 의도하지 않은 Memory Leak를 사전에 방지할 수 있습니다.

class Base {
public:
    Base(): a(nullptr) {
        a = new int(10);
    };

protected:
    ~Base() {
        delete a;
    };

private:
    int* a;
};

class Child: public Base {
public:
    Child() {}
    ~Child() {}
};

위와 Base Class로 Child Class를 관리하게 되면 위와 같이 해당 객체를 소멸시킬 때, 컴파일 에러가 발생하는 걸 볼 수 있습니다.

따라서 Child Class로 직접 사용해야 합니다. 또한 Base Class는 Kotlin의 abstract class 처럼 객체를 생성할 수 없게 됩니다.

 

참고

https://www.youtube.com/watch?v=cOGSbZpNMEw