반응형
계속해서 C++ 게임 서버 사이드 프로젝트로 진행하고 있는데, 이전에 사이드로 만들었던 C# 서버보다는 뭔가 디테일한 부분적으로 설정해줘야하는 부분들이 많아 생각보다 오래 걸리고 있습니다.
디테일한 부분까지 차근차근 보다보니, 하루가 너무 빠르네요.
오랜만에 다시 C++ 게임 서버 만들어보다보니, 재밌기도 하고 어렵기도 하고..
이번에 사이드 프로젝트로 만들고 있다가 shared_ptr 을 클래스 내에서 직접 생성하면 문제가 발생할 수 있다는 부분에 대해 알게 되어 추후에 놓칠 수도 있으니, 남기려고 합니다.
- std::enable_shared_from_this 란?
- 클래스 내부에서
shared_ptr
을 안전하게 생성할 수 있도록 도와주는 유틸리티 - 이걸 사용하면 이미 존재하는
shared_ptr
를 이용해 자기 자신을 공유하는 shared_ptr 생성 가능
- 클래스 내부에서
- 왜 필요할까?
- 클래스 내부에서
shared_ptr(this)
를 직접 생성하면 중대한 오류가 발생
- 클래스 내부에서
예제 코드 ( 오류 발생 )
#include <iostream>
#include <memory>
class MyClass
{
public:
std::shared_ptr<MyClass> GetShared()
{
return std::shared_ptr<MyClass>(this); // 위험한 코드!
}
~MyClass() { std::cout << "Destructor Called\n"; }
};
int main()
{
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
std::shared_ptr<MyClass> ptr2 = ptr1->GetShared(); // 같은 객체를 가리키는 두 개의 shared_ptr 생성
std::cout << "ptr1 count: " << ptr1.use_count() << "\n";
std::cout << "ptr2 count: " << ptr2.use_count() << "\n";
}
결과
ptr1 count: 1
ptr2 count: 1
- 문제점 : 더블 삭제 발생
- 위 코드에서
ptr1
과ptr2
가 서로 다른shared_ptr
인스턴스를 생성하기 때문에 레퍼런스 카운터가 제대로 관리되지 않음 - 결과적으로
MyClass
객체가 두 번 삭제되는 문제가 발생
- 위 코드에서
- → 해결책: enable_shared_from_this()
enable_shared_from_this 사용법
#include <iostream>
#include <memory>
class MyClass : public std::enable_shared_from_this<MyClass>
{
public:
std::shared_ptr<MyClass> GetShared()
{
return shared_from_this(); // 올바르게 shared_ptr을 반환
}
~MyClass() { std::cout << "Destructor Called\n"; }
};
int main()
{
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
std::shared_ptr<MyClass> ptr2 = ptr1->GetShared(); // 올바르게 관리됨
std::cout << "ptr1 count: " << ptr1.use_count() << "\n"; // 2
std::cout << "ptr2 count: " << ptr2.use_count() << "\n"; // 2
}
결과
ptr1 count: 2
ptr2 count: 2
shared_from_this()
를 사용하면ptr1
이 가리키는 기존shared_ptr
을 재사용하기 때문에 레퍼런스 카운트가 정상적으로 증가- 결과적으로 객체가 정상적으로 한 번만 삭제됨.
주요 특징 정리
- 자기 자신을 안전하게
shared_ptr
로 관리 가능 - 객체의 생명 주기 관리가 용이
std::make_shared()
로 생성된shared_ptr
과 함께 사용해야함 (raw pointer 로new
하면std::bad_weak_ptr
예외 발생)
enable_shared_from_this
주의할 점
- 반드시
std::make_shared<T>
로 생성해야함std::make_shared()
를 사용해야 안전
class MyClass : public std::enable_shared_from_this<MyClass> { /* ... */ };
MyClass* obj = new MyClass(); // 직접 new 사용하면 안 됨!
std::shared_ptr<MyClass> ptr(obj);
ptr->shared_from_this(); // std::bad_weak_ptr 예외 발생!
- 다중 상속 시 주의
- 다중 상속 구조에서는
shared_from_this()
가 잘못된 객체를 반환할 수도 있음
- 다중 상속 구조에서는
class Base : public std::enable_shared_from_this<Base> { /* ... */ };
class Derived : public Base { /* ... */ };
std::shared_ptr<Derived> derived = std::make_shared<Derived>();
std::shared_ptr<Base> base = derived->shared_from_this(); // 잘못된 캐스팅 가능성 있음
반응형
'C, C++' 카테고리의 다른 글
[C/C++] 값 복사 방식 vs 참조 방식(feat.매개변수로 const 와 &를 사용하는 이유) (0) | 2025.02.08 |
---|---|
[C/C++] C++ 17 reduce, lcm (2) | 2025.01.21 |
[C++] istringstream, ostringstream, stringstream (0) | 2023.04.25 |
[C#] delegate (대리자) (0) | 2022.10.11 |
[C#] ThreadPool 클래스 (0) | 2022.07.04 |