본문 바로가기

C++/Effective C++11

Effective C++ (51) ~ (55) 51) new 및 delete를 작성할 때 따라야 할 기존의 관례를 잘 알아두자 operator new는 다음과 같은 요구사항을 만족해야 한다. 반환 값이 제대로 되어있어야 함 가용 메모리가 부족할 경우에는 new 처리자 함수를 호출해야 한다 크기가 없는 메모리 요청에 대한 대비책을 갖춰두어야 한다. 기본 형태의 new가 가려지면 안된다. 위 조건을 만족하는 operator new를 의사 코드로 만들면 다음과 같다. void * operator new(std::size_t size) throw(std::bad_alloc) { using namespace std; if (size==0) { size = 1; } while(true){ size 바이트 할당 if(할당 성공시) return 할당된 메모리에 대.. 2021. 8. 29.
Effective C++ (46) ~ (50) 46) 타입 변환이 바람직할 경우에는 비멤버 함수를 클래스 템플릿 안에 정의해 두자. 항목 24에서 모든 매개변수에 대해서 암시적 타입 변환이 되도록 만들기 위해서는 비멤버 함수밖에 방법이 없다는 이야기를 했었다. 이것을 템플릿으로 확장해보자. template class Rational { public: Rational(const T& numerator = 0, const T& denominator = 1); // 매개변수가 참조자로 전달되는 이유는 항목 20 const T numerator() const; const T denominator() const; }; template const Rational operator*(const Rational& lhs, const Rational& rhs) { ... 2021. 8. 28.
Effective C++ (41) ~ (45) 7. 템플릿과 일반화 프로그래밍 41) 템플릿 프로그래밍의 천릿길도 암시적 인터페이스와 컴파일 타임 다형성부터 클래스와 템플릿은 모두 인터페이스와 다형성을 지원한다. 명시적 인터페이스 : 소스 코드에 명시적으로 드러나는 인터페이스 런타임 다형성 : 실제 호출이 동적 타입 기반으로 런타임에 결정되는 경우 암시적 인터페이스 : 제대로 컴파일 되기 위해 필요한 ‘유효한’ 표현식 컴파일 타임 다형성 : 컴파일 도중 인스턴스화가 진행되는 함수 템플릿에 어떤 템플릿 매개 변수가 들어가느냐에 따라 호출되는 함수가 달라지는 경우 클래스의 경우 인터페이스는 명시적이고 함수의 시그니처를 중심으로 구성되어 있다. 다형성은 런타임에 가상함수를 통해 나타난다. 템플릿 매개변수의 경우 인터페이스는 암시적이고 유효 표현식을 기반으.. 2021. 8. 26.
Effective C++ (36) ~ (40) 36) 상속받은 비가상 함수를 파생 클래스에서 재정의하는 것은 절대 금물! 비가상 함수는 정적 바인딩, 가상 함수는 동적 바인딩으로 이루어진다. 만약 비 가상 함수를 재정의하고 호출한다면 호출하는 객체의 타입에따라 동작이 달라진다. 따라서 상속받은 비가상 함수는 절대로 재정의하지 말자. 37) 어떤 함수에 대해서도 상속받은 기본 매개변수 값은 절대로 재정의하지 말자 기본값을 정의해둔 가상 함수의 매개변수는 절대로 상속하면서 파생 클래스에서 값이 달라지거나 하지 않도록 주의하자. 가상 함수 자체는 동적으로 바인딩되어 있지만 기본 매개변수는 정적으로 바인딩되어있다. 이는 런타임 효율을 높이기 위해서이다. 따라서 파생 클래스에 정의된 가상 함수를 사용하면서 매개 변수는 기본 클래스의 매개변수를 사용하게 될 수.. 2021. 8. 25.
Effective C++ (31) ~ (35) 31) 파일 사이의 의존성을 최대로 줄이자 #include는 헤더 파일들 사이에 컴파일 의존성을 만든다. 보통은 전방 선언으로 이러한 문제를 해결한다. 이 때 표준 라이브러리들은 전방 선언을 하지 않는다. precompiled header를 쓰는 환경이라면 더더욱 그럴 필요가 없다. 전방 선언시 pimpl 관용구를 통해 인터페이스와 구현을 분리하면, 구현을 수정했을 때 해당 클래스를 사용하는 다른 부분은 컴파일을 다시 할 필요가 없게 된다. 아래 foo 클래스와 같이 pimpl 관용구를 사용하는 클래스를 핸들 클래스라고 한다. class fooImpl; class foo{ private: std::shared_ptr pImpl; } 컴파일 의존성을 최소화하는 전략은 다음과 같다. 객체 참조자나 포인터로 .. 2021. 8. 24.
Effective C++ (26) ~ (30) 5. 구현 26) 변수 정의는 최대한 늦추자 객체를 선언해 기본 생성한 후 대입하는 방법은 비효율적이다. 기본 생성자를 건너뛸 수 있다면 건너 뛰고 초기화 인자를 얻을 때까지 정의를 미루자. 루프에 대해서는 다음 두가지 선택지가 있다. // A 방법 Widget w; for(int i = 0; i < n; ++i) { w = Widget(i); // i에 따라 달라지는 값 } // B 방법 for(int i = 0; i < n; ++i) { Widget w(i); // i에 따라 달라지는 값 } A 방법은 생성자 1번 + 소멸자 1번 + 대입 n번 B 방법은 생성자 n번 + 소멸자 n번이 불린다. 만약 대입 비용이 생성자+소멸자 쌍보다 적게 드는 경우엔 A가 효율이 좋다. 하지만 그렇지 않을 때엔 B가 .. 2021. 8. 22.
반응형