둠치킨
코딩하는 둠치킨
둠치킨

블로그 메뉴

  • 홈
  • 분류 전체보기 (201)
    • BOJ (159)
      • 스택 (14)
      • 큐 (5)
      • 덱 (4)
      • 그래프 (30)
      • 배열 (8)
      • 재귀 (12)
      • 브루트 포스 (2)
      • 그리디 알고리즘 (7)
      • 다이내믹 프로그래밍 (6)
      • 백트래킹 (24)
      • 기하학 (4)
      • 트리 (4)
      • 구현 (14)
      • 수학 (3)
      • 맵 (1)
      • 다익스트라 (2)
    • 자료구조 (14)
      • 스택 (3)
      • 큐 (5)
      • 덱 (2)
      • 그래프 (1)
      • 트리 (1)
      • 힙 (1)
      • 정렬 (1)
    • C++ (6)
      • 모두의코드 (2)
      • Effective C++ (3)
      • C++ STL (1)
    • 컴파일러 (1)
    • OS (17)
    • 컴퓨터 구조 (2)
    • Unreal Engine 5 (2)

공지사항

전체 방문자
오늘
어제

인기 글

최근 글

태그

  • BFS
  • boj
  • Bruteforce
  • C
  • C++
  • C++ STL
  • Cache Memory
  • deadlock
  • DFS
  • Effective C++
  • java
  • Mutex
  • next_permutation
  • os
  • Process
  • rotate
  • semaphore
  • spin lock
  • STL
  • Thread
hELLO · Designed By 정상우.
둠치킨

코딩하는 둠치킨

C++/Effective C++

Effective C++ 공부 (항목 6 ~ 10)

2025. 6. 24. 19:26

Effective C++ 요약 (항목 6~10)


항목 6: 컴파일러가 만들어주는 함수를 원치 않으면 명시적으로 금지하라

컴파일러는 특별한 요청이 없어도 복사 생성자와 대입 연산자를 자동으로 생성한다. 하지만 어떤 객체는 복사되면 안 되는 경우가 있다.

이럴 땐 다음처럼 private으로 선언하고 구현하지 않기:

class A {
private:
    A(const A&);
    A& operator=(const A&);
};

이러면 외부 복사가 불가능해진다. 만약 friend 함수가 사용하면 컴파일은 되지만 링커 오류 발생.

현대적 방법 (C++11 이후):

class A {
public:
    A(const A&) = delete;
    A& operator=(const A&) = delete;
};
  • 가독성, 유지보수성 증가
  • 의도가 명확하게 드러남

항목 7: 다형성을 가진 기본 클래스에는 가상 소멸자를 반드시 넣어라

다형성(polymorphism)을 지원하는 기본 클래스는 소멸자를 virtual로 선언해야 한다.
그렇지 않으면 파생 클래스 포인터를 기반 클래스 포인터로 삭제할 때 정의되지 않은 동작 발생.

class Base {
public:
    virtual ~Base();  // 반드시 virtual
};

class Derived : public Base {
    ~Derived();
};

추가: 가상 함수가 없어도 추상 인터페이스 클래스를 만들고 싶으면 소멸자를 순수 가상으로:

class Abstract {
public:
    virtual ~Abstract() = 0;
};
Abstract::~Abstract() {} // 정의 필요

주의: STL 컨테이너나 string을 상속하려고 하지 말자. 그들은 가상 소멸자를 갖지 않음.


항목 8: 소멸자에서 예외를 던지지 말자

소멸자에서 예외가 발생하면 다른 예외와 겹쳐져 프로그램이 비정상 종료될 수 있다.

class FileHandle {
public:
    ~FileHandle() {
        try {
            close(); // 예외 발생 가능성 있음
        } catch (...) {
            // 삼켜서 예외 전파 방지
        }
    }
};

더 좋은 방법: 사용자가 명시적으로 close()를 호출하게 만들고, 실패하면 직접 처리하도록 하자.

class FileHandle {
public:
    void close();
    ~FileHandle() {
        try { close(); } catch (...) {}
    }
};

항목 9: 생성자와 소멸자에서 가상 함수를 호출하지 말자

객체의 생성자 또는 소멸자 안에서는 가상 함수가 재정의되지 않은 상태로 호출된다. 아래 예시는 위험하다:

class Transaction {
public:
    Transaction() { LogTransaction(); }  // X 가상 함수 호출
    virtual void LogTransaction() const = 0;
};

해결법: 가상 함수 대신 비가상 함수 호출 + 필요한 데이터를 생성자 매개변수로 전달

class Transaction {
public:
    explicit Transaction(const std::string& logInfo) {
        LogTransaction(logInfo);
    }
    void LogTransaction(const std::string& logInfo);
};

class BuyTransaction : public Transaction {
public:
    BuyTransaction() : Transaction(CreateLogString()) {}
private:
    static std::string CreateLogString();
};

항목 10: 대입 연산자는 *this의 참조를 반환하라

대입 연산자를 연속해서 사용하는 패턴을 허용하려면 *this를 반환해야 한다.

class Widget {
public:
    Widget& operator=(const Widget& rhs) {
        // 대입 처리
        return *this; // this의 참조 반환
    }
};

이것은 다음과 같은 문법을 가능하게 해 준다:

x = y = z = 15;

STL 및 기본형 타입들도 이 규약을 따르므로, 사용자 정의 타입도 따라야 한다.


저작자표시 (새창열림)

'C++ > Effective C++' 카테고리의 다른 글

Effective C++ 공부 (항목 11 ~ 15)  (1) 2025.06.25
Effective C++ 공부 (항목 1 ~ 5)  (0) 2025.06.23
    'C++/Effective C++' 카테고리의 다른 글
    • Effective C++ 공부 (항목 11 ~ 15)
    • Effective C++ 공부 (항목 1 ~ 5)
    둠치킨
    둠치킨
    코딩 공부를 위한 코딩 블로그 기록 일기

    티스토리툴바