리얼 개발

[Effective C++] 공부 정리 4 본문

C++/효과적인 C++

[Effective C++] 공부 정리 4

econo-my 2024. 8. 20. 19:48

항목 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