Special Hot Alien ?! ;-)

More Effective C++ summary

25 Aug 2016

1.포인터와 참조자를 구분하자인데 C++로 넘어오면서 포인터처럼 행동하는 참조자라는 문법이 생겼습니다.

둘중 어느것을 사용해야 좋은지를 설명하였습니다. 참조자는 참조하고자 하는 어떤 객체를 미리 알고 있을때, 다른 객체를 바꾸어 참조할 일이 결코 없을때 (포인터는 이것,저것 주소 대입이 가능하지만 참조자는 한번만 가능합니다.), null 값을 체크할 필요없이 반드시 객체가 존재해야만 할때를 빼고 무조건 포인터를 사용합니다.

2.가능한 C++스타일의 캐스트 연산자를 즐겨 쓰자는것 인데 이 내용은 EC에서도 나왔었습니다.

C스타일의 캐스트는 어떤 타입을 다른 타입으로 아무 생각 없이 바꿔주므로 안정성이 떨어집니다. 그리고 어떤 이유로 캐스트를 했는지 다 똑같이 (cast) 이므로 눈으로 찾아내기가 힘들다는 것입니다. C++의 캐스트 연산자인 static_cast / dynamic_cast / const_cast / reinterpret_cast를 사용 하세요. 사실 EC에서는 웬만하면 캐스트를 사용하지 말라고 했습니다. 정 사용해야 한다면 C++캐스트 연산자를 사용하세요.

3.배열과 다형성은 같은 수준으로 놓고 볼 것이 아니다.

“기반 클래스 포인터를 통해 파생 클래스 객체의 배열을 삭제” 한 결과는 C++언어 스펙에 정의되어 있지 않고, 배열 연산에는 거의 항상 포인터 산술 연산이 따라다니기 때문에, 배열과 다형성은 물과 기름의 관계라는 것입니다.

4.쓸데 없는 기본 생성자는 그냥 두지 말자.

파라미터가 있는 기본생성자만있는경우 객체를 배열로 생성할때, 템플릿 기반의 컨테이너 클래스에 사용될때, 기본 생성자가 없는 가상 기본클래스 개발에 쓰기 힘들다는 것입니다.

5.사용자 정의 타입 변환 함수에 대한 주의를 놓치 말자.

컴파일러가 마음대로 암시적 타입변환을 하도로 내버려 두면 득보다 실이 많다는것. explicit 키워드를 사용하여 암시적 타입변환의 문제를 막을 수 있습니다.

6.증가 및 감소 연산자의 전의/후의 형태를 반드시 구분하자.

UPInt& operator++() ; // 전위++ -> ++i - reference를 반환해서 후위보다 약간 빠르다.
const UPInt oerator++(int) ; // 후위++ -> i++ - temporary obj를 반환하니 약간 느리다.

증가 및 감소 연산자는 전위 형태이던 후위 형태이던 인자를 받지 않도록 되어 있습니다. 이런 난관을 넘기 위해 후의 형태는 int 타입의 인자를 받도록 하고 컴파일러는 후의 형태의 증감 연산자가 호출될때 0을 넘기도록 합니다.

그리고 후의 증감 연삼자는 임시 객체가 필요하므로 전위 증감 연산자보다 효율적입니다.

7.&&, ||, . 연산자는 오버로딩 대상이 절대로 아니다.

8.new 와 delete의 의미를 정확히 구분하고 이해하자.

‘new 연산자’와 ‘operator new’의 차이 !!! new 연산자가 호출하는 그 함수의 이름이 바로 void* operator new(size_t size); 라는것을 알자.

9.리소스 누스를 피하는 방법은 소멸자에 있다.

이 내용은 EC의 RAII(자원 획득 초기화), 즉, 스마트 포인터를 이용하여 자원관리를 하자는 내용과 일맥 상통합니다.

10.생성자에서는 리소스 누스가 일어나지 않게 하자.

C++는 생성과정이 완료된 객체만이 안전하게 소멸자를 호출합니다. 따라서 생성자가 정상적으로 호출되지 않으면 소멸자도 호출되지 않습니다. 생성자에 메모리 누스가 나지 않도록 관리하기 위한 좋은 방법은 역시 스마트 포인터를 이용하는것입니다.

11.소멸자에서는 예외가 탈출하지 못하게 하자. 역시 EC에서도 소개되었던 주제 입니다.

12.예외 발생이 매개변수 전달 혹은 가상함수 호출과 어떻게 다른지를 이해하자.

예외는 값에의한 전달, 참조에 이한 전달, 포인터에 의한 전달 모두 가능하지만 참조에 의한 전달(예외 객체는 항상 복사됩니다. 값에의한 전달은 두번 복사로 효율 저하)을 해야합니다. 그리고 값에의한 전달, 참조에 이한 전달을 하던 예외로 던지는 객체는 사본입니다.

13.발생한 예외는 참조자로 받아내자. 값에의한 전달은 두번 복사되어 효율이 떨어지고 slicing problem 이 도사리고 있습니다.

14.예외 지정기능은 냉철하게 사용하자

15.예외 처리에 드는 비용에 대해 정확히 파악하자.

예외 없이 만든 라이브러리가 훨씬 작고 빠릅니다. try 블록이 소스에 들어가기만 하면 실행크기나 속도에 영향을 미치게 됩니다. try 블록과 예외지정은 꼭 필요한 부분에만 사용합니다.

16.뼛속까지 잊지 말자, 80-20 법칙 ! 전체코드 중에 수행 성능 병목의 원인은20%에 있다. 프로파일러를 사용하여 병목의 원인을 찾고 수정하자는 것입니다.

17.효율 향상에 있어 지연 평가(lazy evaluation)는 충분히 고려해 볼만하다.

지연평가란 미리 계산하지 않고 필요할 때, 즉 요구되어질 때 어떤 행위 (I/O 연산, 산술연산 등)을 수행한다는 것입니다. 그럼 요구 될 때만 비용을 지불하면 되겠습니다.

18,예상되는 계산 결과를 미리 준비하면 처리비용을 깍을 수 있다.

캐싱(Caching)이나 , STL 컨테이너의 메모리 관리방식(Prefetching)등을 예로 들수 있겠습니다.

19,임시 객체의 원류를 정확히 이해하자.

임시객체가 생성되는 원인은 함수 호출을 성사시키기 위해 암시적 타입변환이 적용될 때(상수 객체 참조가가 나온 경우)이고, 객체를 값으로 반환(return by value)할 때입니다. EC 에서도 이 주제를 다룹니다.

20.반환값 최적화(Return Value Optimizaion : RVO)가 가능하게 하자.

값으로 객체를 반환하면서 임시 객체비용이 들지 않는 함수를 작성하는 경우 컴파일러는 실제로 임시 객체의 비용을 없애줍니다. 그 방법이 바로 객체 대신에 생성자 인자를 반환하는 것입니다.

21.오버로딩은 불필요한 암시적 타입변환을 막는 한 방법이다.

22.단독 연산자( +, - ) 대신에 = 이 분은 연산자) +=, -= )를 사용하는것이 좋을 때가 있다.

일반적으로 대입 형태 연산자는 닥독 형태 연산자보다 효율적입니다. 왜냐하면 임시객체를 만들어 놓을 필요가 없기 때문입니다.

23.정 안 되면 다른 라이브러리르 사용하자!

사실 주변에 개발자들 중에서 이미 tr1 까지 구현되어 있고, 광대한 boost library가 있는데도 불구하고 실무에서 자신만의 자료구조를 만들어서 사용하는 경우를 상당히 많이 봤습니다. 고집입니까? 아니면 STL이나 boost를 모르시는 겁니까? STL이나 boost는 이미 여러 전문가들에 의해 인정된 자료구조 알고리즘입니다. 자신이 이 전문가들보다 뛰어나다고 생각하지는 않겠지요(아 죄송합니다. 물론 있을수 있습니다.) 주변의 괜찮은 라이브러리를 사용하는것은 개발 시간 단축에도 큰 영향을 미칩니다. 제발 C함수의 strcpy가 있는데도 자신만의 strcpy를 만들어 사용하는것을 그만 두세요 !!!

24.가상 함수, 다중 상속, 가상 기본 클래스, RTTI 에 들어가는 비용을 제대로 파악하자.

대부분 메모리와 실행코드크기와 효율에 비용이 들어갑니다.

25.생성자 함수와 비 멤버 함수를 가상 함수처럼 만드는방법. 일종의 팩토리 패턴과 프로타입 패턴을 설명하고있습니다.

26.클래스 인스턴스의 개수를 의도대로 제한하는 방법, 싱글톤 패턴과 그 파생적인 설계를 설명합니다.

27.힙에만 생성되거나 힙에는 만들어지지 않는 특수한 클래스를 만드는 방법.

힙에만 객체를 생성할면 protected에 소멸자를 선언합니다. 힙에 만들어지지않게하기위해서는 ‘operator new’와 ‘operator delete’를 private영역에 선언합니다.

28-29.스마트 포인터의 설계시 고민해야 할 문제를 다루며 참조 카운팅 형식의 스마트 포인터의 원리를 설명합니다.

두 주제를 읽고 기존의 다양한 스마트 포인터에 대한 차이점을 알아두는것이 좋을듯합니다. (auto_ptr, shared_ptr, scoped_ptr, scoped_array, weaked_ptr, CComPtr, CComVariant, …..)

30.프록시 클래스

31.함수를 두개 이상의 객체에 대해 가상함수처럼 동작하도록 하기, 다중 디스패치라고 알려진 기법으로 다양안 방법으로 그 구현 방법을 설명하였습니다.

32.미래지향적인 프로그래머가 되자.

33.상속 관계의 말단에 있지 않은 클래스는 반드시 추상 클래스로 만들자.

34.한 프로그램에서 C++와 C를 함께 사용하는 방법을 이해하자.

35.C++언어의 최신 표준안과 표준 라이브러리에 대해 익숙해지자.

Tweet
comments powered by Disqus