센로그
[EC++] 5. C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자 본문
내가 직접 만들지 않으면 컴파일러가 자동으로 만들어주는 것들
컴파일러는 경우에 따라 클래스에 대해 다음 함수들을 암시적으로 정의한다.
- 생성자
- 복사 생성자
- 복사 대입 연산자
- 소멸자
즉, 우리가 다음과 같이 선언했다면
class Empty {};
이렇게 쓴 것과 똑같다는 것이다.
class Empty
{
public:
Empty(){...} // 기본 생성자
Empty(const Empty &rhs){...} // 복사 생성자
~Empty(){...} // 소멸자
Empty& operator=(const Empty &rhs){...} // 복사 대입 연산자
};
이들은 기본적으로 public, inline으로 선언된다.
기본 클래스의 소멸자가 비가상 소멸자라면
- 파생 클래스의 소멸자도 비가상 소멸자로 만들어진다.
기본 클래스의 소멸자가 가상 소멸자라면
- 파생 클래스의 소멸자도 가상 소멸자로 만들어진다.
참조자 멤버가 있는 클래스의 복사 생성자 및 복사 대입 연산자
- 참조자 멤버가 있는 클래스는 복사 대입 연산자 사용이 어렵거나 의미가 없는 경우가 많으므로, 복사 대입 연산자를 delete하여 사용하지 않도록 하는 것이 일반적이다.
class MyClass {
public:
int& ref; // 참조 멤버
// 생성자로 참조 멤버 초기화
MyClass(int& r) : ref(r) {}
// 복사 대입 연산자를 삭제하여 사용하지 못하게 함
MyClass& operator=(const MyClass&) = delete;
};
- 또는 private 멤버로 선언하여 외부로부터의 호출을 차단할 수 있다.
- 선언만 해놓고 정의는 안하는 것이 좋다. 후에 실수로 호출하려 했더라도 링크 시점에 에러를 확인할 수 있기 때문이다.
결론
- 컴파일러가 몰래 만든 함수들로 인해 예상치 못한 오류가 발생할 수 있다는 점을 기억하자.
- 가상 소멸자가 생성되어야 하는데, 비가상 소멸자가 생성될 수 있다.
- 몰래 만들어진 복사 생성자로 인해서 예상치 못한 동작을 할 수 있다.
'Effective > Effective C++' 카테고리의 다른 글
[EC++] 6. 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해 버리자 (2) | 2024.11.13 |
---|---|
[EC++] 4. 객체를 사용하기 전에 반드시 그 객체를 초기화하자 (0) | 2024.11.13 |
[EC++] 3. 낌새만 보이면 const를 들이대 보자! (6) | 2024.11.13 |
[EC++] 2. #define을 쓰려거든 const, enum, inline을 떠올리자 (0) | 2024.11.12 |
[EC++] 1. C++를 언어들의 연합체로 바라보는 안목은 필수 (0) | 2024.11.12 |
Comments