일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- AI
- Unreal Engine
- 게임개발
- 언리얼 엔진5
- 언리얼5
- 게임프로그래밍패턴
- 게임 개발
- C언어
- C++
- Unreal
- 언리얼엔진
- 배열
- 언리얼엔진5
- 프로그래밍
- 복사생성자
- 복사대입연산자
- 데이터구조
- 생성자
- 소멸자
- Unreal Engine5
- effectivec++
- 포인터
- UE5
- 프로세스
- BehaviorTree
- 자료구조
- cpp개발
- 언리얼
- 디자인패턴
- CPP
Archives
- Today
- Total
리얼 개발
[Effective C++] 공부 정리 4 본문
항목 13 : 자원 관리에는 객체가 그만!
- 아래의 코드를 생각해보자
void Func()
{
Klass* klass = new Klass;
...
delete Klass;
}
- 함수 끝의 delete에 도달하기 전에 … 에서 어떤 일이 벌어져서 자원 해제가 되지 않을 수 있다.
- 이런 일을 예방하기 위해 자원을 획득하면 자원 관리 객체에 넘기도록 하자.
- 자원 획득 즉 초기화 (Resource Acquisition Is Initialization : RAII)
- 자원 관리 객체는 자신의 소멸자를 사용해서 자원히 확실히 해제되도록 한다.
- 스마트 포인터는 자원 관리 객체 중 하나이다.
요약
- 사람은 언제나 실수를 안할 수 없다. 자원 누출을 막기 위해, RAII 객체를 사용하도록 하자.
항목 14 : 자원 관리 클래스의 복사 동작에 대해 진지하게 고찰하자
- RAII 객체를 복사하고자 할 때 여러가지 선택지가 있다.
- 복사 금지
- 단순히 복사 연산을 private 멤버로 만든다.
- 관리하고 있는 자원에 대해 참조 카운팅 수행
- 내부적으로 카운팅 변수를 만들어 참조가 0이 되면 delete를 호출한다.
- 원시 포인터 대신 shared_ptr를 사용한다.
- 관리하고 있는 자원 깊은 복사
- 관리하고 있는 자원의 소유권 이전
- 자원의 소유권을 사본 쪽으로 옮긴다.
요약
- RAII 클래스에 구현하는 일반적인 복사 동작은 복사를 금지하거나 참조 카운팅을 해주는 선으로 마무리하는 것이다. 하지만 이 외의 방법들도 가능하니 참고 해두자.
항목 15 : 자원 관리 클래스에서 관리되는 자원은 외부에서 접근할 수 있도록 하자
- 실제 자원을 직접 접근해야 하는 기존 API들도 많기 때문에, RAII 클래스를 만들 때는 그 클래스가 관리하는 자원을 얻을 수 있는 방법을 열어줘야 한다.
- 자원 접근은 명시적 변환 혹은 암시적 변환을 통해 가능하다. 안전성만 따지면 명시적 변환이 대체적으로 더 낫지만, 고객 편의성을 놓고 보면 암시적 변환이 괜찮다.
항목 16 : new 및 delete를 사용할 때는 형태를 반드시 맞추자
- new 연산자의 두가지 동작
- operator new 이름의 함수가 사용되어 메모리 할당 → new도 내부적으로 malloc 을 사용하기 위해 오버로딩 된 함수
- 생성자 호출
- delete 연산자의 두가지 동작
- operator delete 이름의 함수가 사용되어 메모리 해제 → 이 또한 free 를 사용하기 위함
- 소멸자 호출
- new Klass[100] 처럼 배열 객체를 생성했다면 삭제할 때 또한 delete[] 와 같은 표현식을 사용해줘야 한다.
항목 17 : new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자
- 랜덤 숫자를 알려주는 함수가 하나 있고, 동적으로 할당된 Widget 객체에 대해 랜덤한 처리를 하는 함수가 있다고 가정하자.
int Num();
void Func(std::shared_ptr<Widget> pw, int Num);
Func(new Widget, Num()); //컴파일이 되지 않음
Func(std::shared_ptr<Widget>(new Widget), Num()); //자원 누출 가능성 있음
- C++ 컴파일러는 인자를 평가할 때 순서를 자유롭게 할 수 있다.
- 예시로 new Widget이 호출된 후 Num() 을 호출할 때 예외가 발생한다면 new Widget으로 만들어졌던 포인터가 유실될 수 있다.
std::shared_ptr<Widget> pw(new Widget); //하나의 독립적인 문장으로 만들어 넘기자.
Func(pw, Num()) //자원이 누출될 가능성이 없다.
요약
- new로 생성한 객체를 스마트 포인터로 넣는 코드는 별도의 한 문장으로 만들자.
'C++ > 효과적인 C++' 카테고리의 다른 글
[Effective C++] 공부 정리 5 (0) | 2024.10.25 |
---|---|
[Effective C++] 공부 정리 3 (0) | 2024.07.13 |
[Effective C++] 공부 정리 2 (0) | 2024.07.13 |
[Effective C++] 공부 정리 1 (1) | 2024.07.13 |