목록Effective/Effective C++ (13)
센로그

delete는 항상 호출될 것인가?class Investment { ... };Investment* createInvestment(); // Investment 계통에 속한 클래스의 객체를 동적할당하고 그 포인터를 반환void f() { Investment* pInv = createInvestment(); ... delete pInv;};이 코드에서 delete pInv; 가 항상 호출될 것이라고 믿으면 안된다.... 부분에 return 문이 있다면?... 부분에서 예외가 던져진다면?delete 문이 실행되지 않게 된다면, 객체를 담고 있는 메모리가 누출되며, 객체가 갖고 있던 자원도 모두 누수된다. 자원이 항상 해제되도록 만들 수는 없을까?자원을 객체에 넣고, 그 자원 해제를 소멸자가..
커스텀 복사 생성자 및 복사 대입 연산자 구현 시 주의할 점모든 데이터 멤버들을 빠짐없이 복사해야 한다.빠진 요소가 있더라도 컴파일러가 친절하게 알려주지는 않는다. 예시 상황1. 고객을 나타내는 Customer 클래스가 있다.void logCall(const string& funcName);class Customer {public: ... Customer(const Customer& rhs); Customer& operator=(const Customer& rhs); ...private: string name;};Customer::Customer(const Customer& rhs) : name(rhs.name) { logCall("Customer Copy Construc..
자기대입이란?어떤 객체가 자기 자신에 대해 대입 연산자를 적용하는 것을 의미한다.class Widget {...};widget w;...w = w; // 자기대입얼핏 보면 딱히 사용될 일이 없어보인다. 그러나, 다음과 같은 상황은 어떨까?a[i] = a[j];위 구문은 i == j일 때, 자기대입문이 된다.*px = *py;위 구문은 px와 py가 가리키는 대상이 같을 때, 자기대입문이 된다. 자기대입이 생기는 이유는?중복참조(aliasing) 시에 자기 대입이 발생할 가능성이 크다.여러 곳에서 하나의 객체를 참조하는 상태같은 타입으로 만들어진 객체 여러 개를 참조자 혹은 포인터로 물어 놓고 동작하는 코드를 작성할 때는, 같은 객체가 사용될 가능성을 고려하는 것이 바람직하다. 자기대입 시 생길수 있는 문..
C++ 대입 연산은 여러 개가 사슬처럼 엮일 수 있다.int x, y, z;x = y = z = 15;z에 15가 대입되고, 갱신된 z가 y에 대입되고, 갱신된 y가 x에 대입되는 형태이다. 이것이 가능한 이유는?대입 연산자가 좌변 인자(자기 자신)에 대한 참조자를 반환하도록 구현되어 있기 때문이다.이는 일종의 관례이며, 우리가 커스텀 클래스를 만들 때도 대입 연산자는 이런 식으로 구현하는 것이 좋다.class Widget {public: ... Widget& operator= (const Widget& rhs) { ... return *this; } Widget& operator+= (const Widget& rhs) { ... ret..
생성자나 소멸자에서 가상함수를 호출하면 안되는 이유기본 클래스의 생성 과정에서는 가상 함수가 먹히지 않는다.생성자는 기본 클래스 → 파생 클래스 순으로 호출된다.이때 유의할 점: 기본 클래스의 생성자가 호출되는 도중에는, 객체의 타입이 기본 클래스가 된다는 것.기본 클래스의 생성자가 호출되는 동안, 파생 클래스는 초기화된 상태가 아니다.그런데 가상 함수를 파생 클래스쪽에서 호출하면 파생 클래스의 멤버를 건드릴 가능성이 크다.따라서 이런 일을 미연에 방지하기 위해, 이 시점에는 객체의 타입을 아예 기본 클래스로 정해버린다.따라서 호출되는 가상 함수는 모두 기본 클래스의 것으로 결정되며, 런타임 타입 정보(dynamic_cast, typeid 등)도 기본 클래스 타입의 객체로 결정한다.소멸 과정도 똑같다.소..
소멸자에서 예외를 던진다면?소멸자에서 예외를 던진다면 사용자는 예외에 대처할 기회가 없어진다.소멸자는 자원 해제에 많이 사용하므로, 예외를 던지면 자원 해제가 완료되지 않았을 위험이 크다.C++에서는 예외 중첩(이미 처리 중인 예외 + 새로운 예외)이 발생하면 프로그램이 강제종료된다. 소멸자에서 예외를 던질때의 예시크기가 10인 클래스 A타입의 벡터의 소멸자를 호출하는 경우만약 첫번째 원소의 소멸자에서 예외가 발생한다면, 예외를 전파할 것이다.두번째 원소의 소멸자에서도 예외가 발생한다면, 이미 첫번째 예외를 처리중이므로 예외가 중첩된다.C++ 표준에서는 예외가 중첩되면 std::terminate()를 호출하여 프로그램이 강제로 종료된다.DBConnection 클래스의 소멸자에서 db.close()를 호출..