[Effective C++] Ch2. 생성자, 소멸자 및 대입 연산자

y30n9ju1v·2021년 6월 19일
0

프로그래밍

목록 보기
4/18

Item 5. C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자

class empty {};

위와 같이 빈 클래스를 만들었다면 컴파일러는 자동적으로 기본 생성자, 복사 생성자, 복사 대입 연산자, 소멸자를 암시적으로 만듬을 인지해야 함

Item 6. 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해 버리자

어떤 클래스에 대해 복사 생성자나 복사 대입 연산자를 선언하지 않으면 컴파일러가 저절로 만들어내고 public 멤버가 됨
컴파일러에서 자동으로 제공하는 기능을 허용치 않으려면, 대응되는 멤버 함수를 private로 선언한 후에 구현은 하지 않은 채로 두면 됨
만약 코드상에서 구현하지 않은 함수를 사용하려고 하면 linking 에러가 발생할 것이고 이걸로 사용을 금해 버릴 수 있음

Item 7. 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자

다형성을 가진 기본 클래스에는 반드시 가상 소멸자를 선언해야 함
그렇지 않을 경우 파생 클래스에서 정의된 데이터 멤버들이 소멸되지 않음
그렇지만 어느 경우를 막론하고 소멸자를 전부 virtual로 선언하면 안 됨
가상 소멸자를 선언하면 vptr(virtual table pointer)가 생기고 vtbl(virtual table)에 등록이 되는데 vptr 때문에 클래스의 크기가 커짐
이럴 경우 C 등의 다른 언어로 선언된 동일한 자료구조와도 호환성이 없어짐
가상 소멸자를 선언하는 것은 그 클래스에 가상 함수가 하나라도 들어 있을 경우에만 한정해야 함

Item 8. 예외가 소멸자를 떠나지 못하도록 붙들어 놓자

어떤 동작이 예외를 일으키면서 실패할 가능성이 있고 또 그 예외를 처리해야 할 필요가 있다면, 그 예외는 소멸자가 아닌 다른 함수에서 처리되어야 함

Item 9. 객체 생성 및 소멸 과정 중에는 절대로 가상 함수를 호출하지 말자

기본 클래스 생성자는 파생 클래스 생성자보다 앞서서 실행되기 때문에 기본 클래스 생성자가 돌아가고 있을 시점에 파생 클래스 데이터 멤버는 아직 초기화된 상태가 아님
이때 기본 클래스 생성자에서 어쩌다 호출된 가상 함수가 파생 클래스 쪽으로 내려간다면 파생 클래스의 데이터 멤버는 아직 초기화된 상태가 아니기 때문에 미정의 동작을 하게 됨

Item 10. 대입 연산자는 *this의 참조자를 반환하게 하자

int x, y, z;
x = y = z = 15;

위의 코드를 풀어 보면 15가 z에 대입되고 갱신된 z가 y에 대입되고 다시 갱신된 y가 x에 대입됨
이런 구현은 일종의 관례임

Item 11. operator=에서는 자기대입에 대한 처리가 빠지지 않도록 하자

operator=을 구현할 때 어떤 객체가 그 자신에 대입되는 경우를 제대로 처리하도록 해야 함
원본 객체와 복사 대상 객체의 주소를 비교해도 되고 복사 후 맞바꾸기를 써도 됨
그러나 프로그램에서 자기 대입이 얼마나 일어날까? 복사 대상 객체의 주소를 비교하는 것은 분기를 일으키고 그만큼 느리게 만듦
두 개 이상의 객체에 대해 동작하는 함수가 있다면 이 함수에 넘겨지는 객체들이 사실 같은 객체인 경우에 정확하게 동작하는지 확인이 필요함

Item 12. 객체의 모든 부분을 빠짐없이 복사하자

파생 클래스에 대한 복사 함수를 스스로 만든다고 결심했다면 기본 클래스 복사를 빠뜨리지 않도록 해야 함
기본 클래스 부분은 private 멤버일 가능성이 아주 높기 때문에 이들을 직접 건드리긴 어려움
그 대신에 파생 클래스의 복사 함수 안에서 기본 클래스의 복사 함수를 호출해야 함

0개의 댓글