2. Constructors, Destructors, and Assignment Operators

5. Know what functions C++ silently writes and calls.

컴파일러는 기본적으로 생성자 (따로 정의하지 않는다면), 복사 생성자, 이동 생성자, 복사 대입 연산자, 이동 대입 연산자를 제공한다. const 멤버나 참조자 멤버가 있는 경우 복사 생성자나 이동 생성자를 따로 정의해줘야 한다.

  • 컴파일러는 기본 생성자, 복사 생성자, 복사 대입 연산자, 이동 생성자, 이동 대입 연산자, 소멸자를 필요에 따라 생성해 준다.

6. Explicitly disallow the use of compiler-generated functions you do not want.

복제를 막기 위해서라면 복사 생성자와 복사 대입 연산자를 delete한다.

  • 복제를 막기 위해서라면 복사 생성자와 복사 대입 연산자를 delete한다.

7. Declare destructors virtual in polymorphic base classes.

파생 클래스 오브젝트가 non-virtual 소멸자를 가진 기반 클래스 포인터를 통해 삭제될 경우의 동작은 정의되어 있지 않다. 그러므로 다형성을 위한 기반 클래스의 소멸자는 반드시 virtual로 정의해야 한다. 기반 클래스로 쓰이지 않는 클래스는 오브젝트 사이즈 증가를 막기 위해 virtual을 쓰지 말고, final로 마킹하자.

std::string, std::unordered_map은 virtual 소멸자가 없으므로 이로부터 다형성을 위한 파생 클래스를 만들면 안 된다. 소멸자를 = 0을 통해 순수 가상 함수로 정의하면 추상 클래스로 만들 수 있다.

  • 다형 기반 클래스는 virtual 소멸자를 선언해야 한다. virtual 멤버 함수가 존재한다면 virtual 소멸자를 선언해야 한다.
  • 다형 기반 클래스가 아닌 기반 클래스에는 virtual 함수를 선언하지 말라. 기반 클래스로 쓰이지 않는 클래스는 final로 선언하라.

8. Prevent exceptions from leaving destructors

클래스의 소멸자에서 예외를 던지지 말라. 컨테이너 등에서 소멸자가 여러 번 불릴 때 같은 예외가 여러 번 불리면 정의되지 않은 행동이 일어난다. 해결책은 두 가지이다: 소멸자 내에서 예외가 던져질 때 프로그램을 종료하거나, 소멸자 내에서 예외를 catch로 삼키거나. 아니면 소멸자 내에서 예외를 던지는 함수의 에러 처리 책임을 클래스의 클라이언트에게 넘기는 방법도 좋다.

  • 소멸자는 절대 예외를 던져선 안 된다. 소멸자 내에서 예외가 던져질 때에는 프로그램을 종료하거나 소멸자 내에서 예외를 catch로 삼켜야 한다.
  • 클래스의 클라이언트가 동작이 던지는 예외와 상호작용해야 한다면 그 예외를 던지는 함수를 비-소멸자 멤버 함수로 이동시켜라.

9. Never call virtual functions during construction or destruction.

생성자에서 가상 함수를 호출하지 말라. 기반 클래스의 생성자에서는 파생 클래스의 가상 함수가 아니라 기반 클래스의 가상 함수가 불리기 때문이다. 이는 기반 클래스의 생성자가 실행되는 도중에는 파생 클래스의 멤버 변수가 초기화되지 않았을 것이기 때문에 이를 사용하는 것을 막기 위함이다. 소멸자에서도 마찬가지다. 여러 생성자들간에는 생성자 호출이 가능하므로 이를 통해 중복 코드를 막자.

  • 생성자나 소멸자에서 가상 함수를 호출하지 말라. 클래스 계층 내 다른 클래스의 가상 함수를 호출하지 않기 때문이다.

10. Have assignment operators return a reference to *this.

모든 대입 연산자는 *this의 참조를 반환하도록 하라.

  • 모든 대입 연산자는 *this의 참조를 반환하도록 하라.

11. Handle assignment to self in operator=.

대입 연산자에서 자가 대입 문제를 피하라.

  • operator= 에서 자가 대입 문제를 피하라. 두 오브젝트간 주소를 비교하는 방법이나, 명령문 순서를 잘 조절하는 법, 복제 후 swap을 하는 법 등이 있다.
  • 여러 오브젝트를 다루는 함수의 경우 두 오브젝트가 같은 경우에 대해서 잘 대처하라.

12. Copy all parts of an object.

복사 생성자나 복사 대입 연산자에서는 항상 클래스의 모든 부분을 복사하도록 해야 한다. 이는 포인터 멤버나 기반 클래스 부분을 다룰 때 특히 주의해야 한다.

  • 복제 함수는 오브젝트의 모든 데이터 멤버와 기반 클래스 부분을 복제하는 것을 보장해야 한다.
  • 여러 복제 함수간 상호간 호출을 하지 말라.

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google photo

Google의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중