Search

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

개요

C++에서 컴파일러는 특정 상황에서 자동으로 몇 가지 멤버 함수를 생성합니다. 이는 대부분의 경우 편리하지만, 때로는 원치 않는 동작을 초래할 수 있습니다. 이번 글에서는 Effective C++의 여섯 번째 항목을 통해 이러한 자동 생성 함수의 사용을 어떻게 효과적으로 제한할 수 있는지 살펴보겠습니다. 이는 특히 객체의 복사가 의미가 없거나 위험한 상황에서 중요한 기법입니다.

본문

문제 상황: 복사할 수 없는 객체

부동산 중개 소프트웨어를 개발한다고 가정해봅시다. 이 시스템에는 매물로 내놓은 집을 나타내는 HomeForSale 클래스가 있습니다.
class HomeForSale { // ... 클래스 내용 ... }; HomeForSale h1; HomeForSale h2; HomeForSale h3(h1); // 복사 생성자 호출 h1 = h2; // 복사 대입 연산자 호출
C++
복사
여기서 문제는 부동산에서 모든 자산은 유일해야 한다는 점입니다. 따라서 HomeForSale 객체를 복사하는 것은 논리적으로 맞지 않습니다. 하지만 위 코드는 컴파일러가 자동으로 복사 생성자와 복사 대입 연산자를 생성하기 때문에 문제없이 컴파일됩니다.

해결 방법 1: private 선언

첫 번째 해결 방법은 복사 생성자와 복사 대입 연산자를 private로 선언하는 것입니다.
class HomeForSale { public: // ... 다른 public 멤버들 ... private: HomeForSale(const HomeForSale&); // 선언만 있고 정의는 없음 HomeForSale& operator=(const HomeForSale&); // 선언만 있고 정의는 없음 };
C++
복사
이 방법은 외부에서의 복사를 막을 수 있지만, 클래스의 멤버 함수나 friend 함수에서는 여전히 접근이 가능합니다. 이를 완전히 막으려면 선언만 하고 정의를 하지 않으면 됩니다.

해결 방법 2: Uncopyable 기본 클래스 사용

두 번째 방법은 복사를 방지하는 기본 클래스를 만들고 이를 상속받는 것입니다.
class Uncopyable { protected: Uncopyable() {} ~Uncopyable() {} private: Uncopyable(const Uncopyable&); Uncopyable& operator=(const Uncopyable&); }; class HomeForSale : private Uncopyable { // ... 클래스 내용 ... };
C++
복사
이 방법을 사용하면 HomeForSale 객체의 복사 시도 시 컴파일 에러가 발생합니다. 이는 Uncopyable의 private 복사 생성자와 복사 대입 연산자에 접근할 수 없기 때문입니다.

개인적 견해

이 방법은 복사를 방지하는 데 효과적이지만, 한계가 있습니다. private 선언 방식은 코드의 의도를 명확히 전달하지 못하고, Uncopyable 기본 클래스 상속 방식은 다중 상속 시 문제가 될 수 있습니다. 이에 대해 Modern Effective C++에서는 더 명확한 방법을 제시합니다. C++11부터 도입된 delete 키워드를 사용하면 함수를 명시적으로 삭제할 수 있어, 코드의 의도를 더 명확히 전달할 수 있습니다.

결론

컴파일러가 자동으로 생성하는 함수의 사용을 제한하는 것은 때로 필요하며, 이를 위해 private 선언이나 Uncopyable 기본 클래스 상속 등의 방법을 사용할 수 있습니다. 하지만 C++11에서 제공하는 delete 키워드 같은 더 명확한 방법도 있으므로, C++ 개발자로서 지속적으로 새로운 기법들을 학습하고 적용하는 것이 중요합니다.