일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- VR
- OculusMotionVectorPass
- Virtual Byte
- 메모리 누수
- Private Bytes
- Cell Shader
- Toon Shader
- 개인 바이트
- working set
- 가상 바이트
- 게임 수학
- Cartoon Rendering
- 작업 집합
- C언어
- URP로 변경
- ColorGradingLutPass
- 프로그래밍 기초
- URP
- AppSW
- Specular
- ASW(Application SpaceWarp)
- Three(Two) Tone Shading
- Rim Light
- 3d
- 벡터
- Windows Build
- Cell Look
- Today
- Total
WinCNT
스마트 포인터 본문
메모리를 동적 할당할 경우는 반드시 delete를 해줘야 한다
문제는 Block 안(특히 함수 등)에서 메모리를 동적 할당할 경우이다
블록을 벗어나면 포인터 변수에는 접근할 수 없으니 해제가 불가능해진다
심지어 new-delete를 제대로 해줬다고 해도 다음과 같이 throw가 있으면 문제가 발생할 수 있다
void foo()
{
double* pDouble { new double };
*pDouble = 3.14;
throw...; //
delete pDouble;
}
malloc과 new의 차이
malloc - free의 경우 free할 때 소멸자가 호출되지 않는다
new - delete의 경우 delete할 때 자동으로 소멸자가 호출된다
즉, 객체(클래스) 생성에는 반드시 new - delete를 써야한다
포인터의 문제점
포인터가 가리키는 주소의 값이 배열인지 하나의 객체인지 판별 불가능 --> 포인터 선언의 타입
파괴하기 위해 어떤 방식을 써야할지 알아낼 방식이 없다 --> delete? delete[]??
포인터가 가리키는 대상을 내가 소유하는지 아닌지 알 수 없다 --> 배타적 소유권
댕글링 포인터(Dangling pointer), 자원이 이미 해제된 자원인지 아닌지 판별할 수 없다 --> nullptr
자원 해제는 정확히 한 번만 해야한다 --> 중복해제 방지
// 재할당
while(true)
{
int* ptr = new int; // 기존의 new int에 접근할 수 없게 된다
}
위의 문제점을 해결하기 위해 C++11에서는 스마트 포인터가 등장했다
스마트 포인터의 개요
<memory> 헤더 파일에 존재
C++에서는 메모리 누수로부터 프로그램의 안전성을 보장하기 위해 스마트 포인터를 제공
스마트 포인터란 포인터처럼 동작하는 클래스 템플릿으로
사용이 끝난 메모리를 자동으로 해제해준다
unique_ptr<> : 배타적 소유권
shared_ptr<> : 공유 자원 관리
weak_ptr<> : shared_ptr를 보완하기 위해 사용
unique_ptr의 예
class Foo
{
public:
Foo() { cout << "생성\n"; }
Foo(int) { cout << "생성(int)\n"; }
~Foo() { cout << "소멸\n"; }
void func() {}
};
int main()
{
Foo* ptr = new Foo();
delete ptr;
// 내가 생성한 객체를 스마트 포인터가 관리하라는 느낌
unique_ptr<Foo> smartPtr1(new Foo()); // C++11
// 위의 코드를 보완한 것
unique_ptr<Foo> smartPtr2 = make_unique<Foo>(); // C++14
auto smartPtr3 = make_unique<Foo>();
cout << "중괄호 start\n";
{
auto smartPtr4 = make_unique<Foo>();
}
cout << "중괄호 end\n";
return 0;
}
RAII(Resource Acquisition Is Initialize) 패턴
객체 생성 시에 할당한 메모리에 대해서
소멸자 호출 시에 해제하도록 하면 메모리 관리가 수월해진다!
/// <summary>
/// RAII 패턴 예제
/// </summary>
class MyString
{
public:
char* c = nullptr;
MyString(size_t len) { c = new char[len]; }
~MyString() { delete[] c; }
};
스마트 포인터는 다음과 같이 만들 수 있다
class MyString
{
public:
char* c = nullptr;
MyString(size_t len)
{
cout << "MyString 자원 획득함!\n";
c = new char[len];
}
~MyString()
{
cout << "MyString 자원 delete!\n";
delete[] c;
}
void func() { cout << c << endl; }
};
class MyString_SPtr
{
MyString* data;
public:
MyString_SPtr(MyString* d):data(d) { }
~MyString_SPtr() { delete data; }
MyString& operator*() const { return *data; }
MyString* operator->() const { return data; }
};
unique_ptr는 위의 클래스를 템플릿화한 느낌의 std이다
SSS
'게임 프로그래밍(학습 내용 정리) > Modern C++' 카테고리의 다른 글
배열 포인트와 _countof(혹은 ARRAYSIZE) (0) | 2022.06.14 |
---|---|
스마트 포인터 - unique_ptr (0) | 2022.04.21 |
decltype과 Value Category(lvalue, rvalue, xvalue) (0) | 2022.03.24 |
범위 기반 for문 (0) | 2022.03.24 |
Modern C++ - Auto (0) | 2022.03.24 |