[Effective C++ 정리 #6] 복사 금지! 컴파일러가 몰래 만든 함수 차단 방법
이 글은 『Effective C++』를 읽고 개인적으로 공부한 내용을 정리한 기록입니다.
저는 컴퓨터공학을 전공하지 않았으며, 프로그래밍을 공부하는 과정에서의 이해와 생각을 정리하기 위해 글을 작성하고 있습니다.
따라서 내용 중 일부에 오류나 부정확한 설명이 있을 수 있으며, 피드백은 언제든지 환영합니다. 확인 후 수정하도록 하겠습니다.
전문적인 해설이 아닌 개인적 시선에서의 정리임을 참고하고 읽어주시면 감사하겠습니다.
[Effective C++ 정리 #6] 복사를 막고 싶다면 컴파일러가 만든 함수부터 차단하라
C++ 컴파일러는 우리가 명시하지 않아도 복사 생성자와 복사 대입 연산자를 자동으로 만들어줍니다. 하지만 어떤 클래스는 복사가 허용되어선 안 됩니다. 예를 들어, '집 한 채'를 복사해서 또 다른 동일한 집을 만든다는 건 말이 안 되죠.
이번 아이템에서는 '복사가 의미 없는 클래스'에서 복사를 방지하는 안전하고 명확한 방법을 공부합니다.
복사를 허용하면 안 되는 경우
예를 들어, 부동산 중개 시스템에 아래와 같은 클래스가 있다고 가정해 봅시다.
class HomeForSale { ... };
모든 매물은 고유합니다. 따라서 HomeForSale
객체는 복사될 수 없도록 막아야 합니다.
HomeForSale h1;
HomeForSale h2;
HomeForSale h3(h1); // ❌ 복사 생성자 사용 — 막고 싶음
h1 = h2; // ❌ 복사 대입 연산자 사용 — 막고 싶음
문제는 우리가 복사 생성자나 대입 연산자를 작성하지 않더라도, 컴파일러가 자동으로 이 함수들을 생성해버린다는 데 있습니다.
어떻게 복사를 막을 수 있을까?
복사를 막기 위한 기본 전략은 다음과 같습니다:
- 복사 생성자와 복사 대입 연산자를 직접 선언하여 컴파일러의 자동 생성을 막는다.
- 이들을 private으로 선언하여 외부 접근을 차단한다.
- 정의는 하지 않는다. (링크 단계에서 에러 발생)
즉, 다음과 같이 선언만 하고 구현하지 않는 패턴을 사용합니다.
class HomeForSale {
public:
HomeForSale(); // 생성자는 public
~HomeForSale(); // 소멸자도 public
private:
HomeForSale(const HomeForSale&); // 복사 생성자 (선언만)
HomeForSale& operator=(const HomeForSale&); // 복사 대입 연산자 (선언만)
};
이렇게 하면 컴파일러는 더 이상 자동 생성을 하지 않고, 누군가 복사를 시도할 경우 컴파일 또는 링크 오류가 발생합니다.
이 방식은 C++ 표준 라이브러리의 iostream
계열 클래스 (ios_base
, basic_ios
등)에서도 널리 사용됩니다.
더 세련된 방식: Uncopyable 베이스 클래스
복사를 막기 위해 매번 private 복사 생성자와 대입 연산자를 선언하는 건 번거롭습니다. 이럴 때는 다음처럼 베이스 클래스를 활용하면 훨씬 깔끔하게 구현할 수 있습니다.
class Uncopyable {
protected:
Uncopyable() {}
~Uncopyable() {}
private:
Uncopyable(const Uncopyable&);
Uncopyable& operator=(const Uncopyable&);
};
이제 Uncopyable
을 상속만 하면, 그 클래스는 자동으로 복사가 금지됩니다.
class HomeForSale : private Uncopyable {
...
};
이 방식은 다음과 같은 장점이 있습니다:
- 코드 중복이 없고 일관성 유지
- 의도가 명확하여 유지보수성 향상
- 링크 에러 대신 컴파일 에러 발생 가능 (더 빠른 피드백)
Boost 라이브러리에는 이와 동일한 역할을 하는 noncopyable
클래스가 존재합니다. #include <boost/noncopyable.hpp>
를 통해 간단히 사용할 수 있습니다.
핵심 요약
- 복사를 막고 싶다면, 해당 함수들을 private 선언 + 미구현으로 해결 가능하다
Uncopyable
같은 베이스 클래스를 활용하면 반복을 줄이고 명확성을 높일 수 있다.
감사합니다.