more effective c++ 챕터3~4ppt

48
More Effective C++ 정정 131054 정정정

Upload: cowspirit

Post on 23-Jun-2015

121 views

Category:

Education


7 download

DESCRIPTION

Effective C++ Summary

TRANSCRIPT

Page 1: More effective c++ 챕터3~4ppt

More Effective C++ 정리

131054 이인재

Page 2: More effective c++ 챕터3~4ppt

예외처리

1. 예외처리는 만들기 어렵다 -> 생성자와 소멸자를 만들기보다 더 힘듦

2. 예외처리할때 문제점-> 어떻게 해야 제대로 예외처리를 하는 것인지 잘 모름

3. 예외를 고려하지 않을때 문제점-> 예외 발생 상황에서 의도한 대로 잘 동작하지 않음

Page 3: More effective c++ 챕터3~4ppt

항목 9 : 리소스 누수를 피하는 방법의 정공은 소멸자

1. 예외 처리가 되어있지 않을때에 메모리 누수가 발생할 수 있다-> 포인터처럼 동작하는 객체가 소멸될 때 이 객체의 소멸자에서 delete 를 호출하도록 만들면 된다

2. 포인터처럼 동작하는 객체란 ? -> 스마트 포인터

3. C++ 라이브러리에서 auto_ptr 을 제공

Page 4: More effective c++ 챕터3~4ppt

메모리 누수 위험성 있는 코드1. delete pa 가 실행이 되지 않아버리면 ? 메모리

누수

Page 5: More effective c++ 챕터3~4ppt

auto_ptr 을 이용한 코드1. auto_ptr 객체가 사라질 때 delete 호출

Page 6: More effective c++ 챕터3~4ppt

예외처리시 주의사항

1. 동적 할당 리소스는 객체로 포장을 해라

2. 예외발생 시 메모리누수의 위험성을 인지해라

3. auto_ptr 을 이용하여 관리

Page 7: More effective c++ 챕터3~4ppt

항목 10 : 생성자에서는 리소스 누수가 일어나지 않게하자

1. C++ 은 생성 과정이 완료된 객체만을 안전하게 소멸시킴

2. 생성자가 실행을 마치기 전에는 생성 작업이 완료되지 않은 것으로 간주

3. 소멸자도 역시나 안전하게 호출되지 않음

Page 8: More effective c++ 챕터3~4ppt

생성자에서의 예외처리1. 포인터 클래스 멤버를 auto_ptr 로 바꿈

-> 생성자는 실행도중에 예외가 발생하더라도 리소스 누수를 일으키지 않음 , 소멸자에서 직접 리소스를 해제하지 않아도 됨 , 상수 멤버포인터 및 비상수 포인터와 똑같이 처리 가능

2. 객체 생성중에 발생할 수 있는 예외에 대한 대처 방안은 관점에 따라 충분히 까다로울 수 있음-> auto_ptr 또는 이와 비슷한 클래스 이용

Page 9: More effective c++ 챕터3~4ppt

항목 11: 소멸자에서는 예외가 탈출하지 못하게 하자

1. 클래스 소멸자가 호출되는 경우-> 지역변수로 선언된 객체가 유효범위를 벗어났을 때 , 객체가 직접 삭제될 때

2. 객체가 직접삭제될 떄는 예외 처리 매커니즘에 의해 객체가 소멸되는 것

3. 즉 소멸자가 호출되었을 때는 예외 처리가 발생된 상태일 수도 있고 아닐 수도 있음-> 방어적으로 , 어떤 상황에서든 예외가 발생된 상태에 있다고 가정하고 소멸자 작성

Page 10: More effective c++ 챕터3~4ppt

예외가 소멸자를 빠져나가지 못하게 해야 하는 이유

1. 예외 전파의 일부분으로서 진행되는 스택 되감기 동작 중에 terminate 가 호출되는 것을 막기 위해서 .

2. 소멸자의 동작을 완전히 끝내도록 하기 위해서

Page 11: More effective c++ 챕터3~4ppt

항목 12: 예외 발생이 매개변수 전달 혹은 가상 함수 호출과 어떻게 다른지를

이해하자1. 함수로의 매개변수전달 , catch 문으로의

예외전달의 유사점-> 값에 의한 전달 , 참조에 의한 전달 , 포인터에 의한 전달이 가능

2. 함수로의 매개변수전달 , catch 문으로의 예외 전달의 차이점-> 함수를 호출했을 때에는 프로그램의 흐름이 함수를 호출한 부분으로 되돌아오지만 , 예외는 프로그램 흐름이 throw 를 호출한 부분으로 되돌아오지 않음

Page 12: More effective c++ 챕터3~4ppt

정리1. 예외 객체는 항상 복사된다

-> 특히 값에 의한 예외 처리의 경우에는 두 번 복사

2. 함수 매개변수로 전달되는 객체는 복사되지 않음

3. 발생되는 예외는 전달되는 매개변수에 비해 타입변환을 거치는 가지수가 적음

4. catch 문은 소스 코드에 등장한 순서대로 동작 , 예외를 처리할 수 있는 catch 문 중에 가장 첫째 것이 선택

Page 13: More effective c++ 챕터3~4ppt

항목 13 : 발생한 예외는 참조자로 받아내자

1. catch 문을 작성할 때에는 예외 객체가 전달되는 방식을 설정해야 함

2. 포인터에 의한 전달

3. 값에 의한 전달

4. 참조자에 의한 전달

Page 14: More effective c++ 챕터3~4ppt

포인터에 의한 전달1. 포인터에 의한 예외받기가 가장 효율적이어야

함-> 예외를 포인터로 발생시키면 객체의 복사 없이도 전달이 이루어지기 때문

2. 소멸된 객체애 대한 쓸데없는 포인터받아내는 문제를 피해야 함

3. 포인터에 의한 예외받기는 피하는 것이 가장 좋음-> 죽이느냐 살리느냐 하는 것에 대한 답이 없기 때문

Page 15: More effective c++ 챕터3~4ppt

값에 의한 예외받기

1. 예외를 삭제하느냐 마느냐의 고민을 없애줌

2. C++ 표준 예외하고 잘 맞음

3. 객체가 두 번씩 복사되어야 함

4. 슬라이스 현상 발생-> 발생 시에는 파생 클래스의 객체였따가 기본 클래스를 받는 catch 문에 들어가면서 파생 클래스 부분에 추가되었던 데이터가 싹둑 잘려 나가는 현상

Page 16: More effective c++ 챕터3~4ppt

참조자에 의한 예외받기

1. 객체 삭제애 대한 고민을 할 필요 없음

2. 슬라이스 문제가 생기지 않고 , 예외 객체는 한 번만 복사

3. 즉 참조자를 이용한 예외받기를 통해 앞선 두 개의 방법에서 발생했던 문제를 해결 가능

Page 17: More effective c++ 챕터3~4ppt

항목 14 : 예외 지정기능은 냉철하게 사용하자

1. 함수가 발생시킬 예외를 미리 지정할 수 있는 기능

2. 어떤 함수가 어떤 예외를 발생시키는지가 드러나기 때문에 코드보기가 수월

3. 예외 지정에 일관성이 없으면 컴파일러가 알려줌

4. 함수가 예외 지정 리스트에 없는 예외를 발생 시킬 경우 런타임 에러발생

Page 18: More effective c++ 챕터3~4ppt

예외지정 사용시 주의점1. 예외 지정 리스트에 없는 예외를 발생시킬

경우 런타임 에러가 발생하면서 unexpected 라는 특수 함수가 자동으로 호출 -> terminate 를 호출하는 것인데 이는 기본적으로 abort 호출 . 예외 지정을 어긴 프로그램은 바로 멈춤

2. 활성 스택 프레임에 만들어진 지역변수는 없어지지 않음

3. 의외로 이런 함수를 만들기가 쉬움

Page 19: More effective c++ 챕터3~4ppt

예외지정 문제점 예방법1. 템플릿과 예외 지정은 섞여선 안됨

-> 템플릿의 타입 매개변수에서 발생된 예외에 대해서는 알 방법이 전혀없고 , 템플릿에는 예외지정을 하는 것 자체가 무의미( 매우 무궁무진한 타입이 올 수 있기 때문 )

2. 예외 지정이 안 된 함수를 호출할 가능성을 가진 함수에는 예외 지정을 두지 않아야 함

3. “시스템”이 일으킬 가능성이 있는예외를 처리

Page 20: More effective c++ 챕터3~4ppt

항목 15 : 예외 처리에 드는 비용에 대해 정확히 파악

1. 실행중 예외 처리를 위해 C++ 프로그램은 내부적으로 상당히 많은 정보를 유지 -> 여기에 들어가는 비용도 당연히 생김

2. 에외가 발생했을 때 소멸시켜야 할 객체를 파악 , try블록으로 들어갈 떄와 바쪄나올 때의 상황을 점검 , 각각의 try 블록마다 catch 문을 추적

3. 컴파일러마다 예외처리에 들어가는 비용이 다름-> 예외처리 구현이 다르게 되어있기 때문

Page 21: More effective c++ 챕터3~4ppt

try블록으로 인해 생기는 비용

1. try블록이 소스에 들어가기만 하면 , 즉 예외를 처리하겠다고 작정하면 무조건 지불해야하는 비용-> 컴파일러마다 구현하는 방법이 다르기 때문에 , 이 비용 역시 컴파일러마다 다름

2. try 블록을 썻을 경우 늘어나는 코드 크기와 실행 속도는 5~10% 정도-> 이 비용을 줄이려면 쓸데없이 try블록을 남발하지 않아야 함

Page 22: More effective c++ 챕터3~4ppt

예외 지정 기능에서 발생하는 비용

1. try 블록과 비슷한 양의 코드가 생성되기 때문에 , 예외 지정에 들어가는 비용도 try 블록고 비슷

2. 예외 지정 시 예외 지정을 위한 코드가 생성되기 때문에 비용이 발생

Page 23: More effective c++ 챕터3~4ppt

예외 처리에 발생하는 비용에 관하여

1. 예외 발생시 소모되는 비용은 그다지 큰 관심거리가 되지 못함-> 예외 발생의 확률이 극히 낮기 때문

2. 단 , 프로그램에서 꽤 자주 발생하는 상황에서의 예외는 심각하게 다루어야 함

3. 그렇다고 함부로 예외 코드를 남발하면 안됨

Page 24: More effective c++ 챕터3~4ppt

비용에 대해 대비하는 법

1. 예외에 관련된 비용을 최소화하려면 , 우선 가능한한 예외 기능일 지원하지 않도록 컴파일

2. try 블록과 예외 지정은 꼭 필요한 부분에만 사용

3. 예외를 발생시키는 일도 진짜 예외적인 상황이라고 판단될 떄에만 해야 함

4. 예외 처리 기능을 더 효율적으로 구현한 컴파일러 사용

Page 25: More effective c++ 챕터3~4ppt

효율1. 효율은 C++ 프로그램의 생명이자 숙명

2. 아무리 기능이 우수하다고 해도 덩치가 크고 속도가 느린 프로그램은 용서가 안됨

3. 설계에서 문제가 비롯되었을 수 있음

4. 효율적인 프로그램을 작성하고자 한다면 우선 효율적으로 프로그램 자체를 만들 줄 알아야 함-> 루프는 경우에 따라서는 풀엇 , 곱셉은 쉬프트 등

Page 26: More effective c++ 챕터3~4ppt

항목 16 : 80-20 법칙의 중요성1. 프로그램 리소스의 80% 는 전체 실행 코드의

약 20% 만이 사용

2. 실행 시간의 80% 는 실행 코드의 약 20%만이 소모

3. 메모리의 80% 는 실행 코드의 약 20% 만이 사용

4. 디스크 접근 회수의 80% 는 실행 코드의 20% 가 접근환 회수

5. 프로그램 유지보수에 들어가는 수고의 80%는 실행 코드의 20% 에 집중

Page 27: More effective c++ 챕터3~4ppt

수행 성능에 문제가 있을때

1. 수행 성능에 문제가 있다면 성능의 발목을 잡고 있는 코드를 찾아야 함

2. 찾았다면 그 코드를 극적으로 개선해야 성능이 좋아짐

3. 병목 현상을 일으키는 부분을 찾는 것이 중요

Page 28: More effective c++ 챕터3~4ppt

수행 성능을 향상 시켜라

1. 아무 곳이나 골라잡고 효율을 향상시키려고 애쓰는 것은 별 도움이 안됨

2. 성능을 향상시키기 위해서는 20% 의 코드를 경험적으로 판별하는 것도 필요함

3. 시간 측정을 해 주는 프로파일러를 이용하여 개선시켜야 할 곳을 찾아냄

Page 29: More effective c++ 챕터3~4ppt

항목 17 : 효율 향상에 있어 지연 평가는 충분히 고려해 볼 만하다

1. 어떤 일을 하긴 하되 그 일을 하는 코드의 실행을 피하는 방법

2. 지연 평가를 사용해서 만든 C++ 클래스는 어떤 처리 결과가 진짜로 필요해질 때까지 그 처리를 미룸

3. 지연 평가를 적용할 수 있는 일반적인 경우의 4 가지가 있음

Page 30: More effective c++ 챕터3~4ppt

참조 카운팅

1. 자기만의 데이터 사본을 만들지 않고 , 남이 만들어 놓은 사본을 빌어다 쓰는 것

2. 경우에 따라서는 끝까지 남의 것만으로 연명가능

Page 31: More effective c++ 챕터3~4ppt

데이터 읽기와 쓰기를 구분하기

1. 참조 카운팅에의해 유지되는 문자열은 읽기에는 좋지만 쓰기에는 불편

2. 쓰기가 이루어지느냐 읽기가 이루어지느냐에 따라 다른 동작이 수행되도록 할때 구분이 필요함

3. 지연 평가와 프록시 클래스를 사용하면 읽기가 맞는지 쓰기가 맞는지를 정확히 결정할 수 있을 때까지 동작을 늦출 수 있음

Page 32: More effective c++ 챕터3~4ppt

지연 방식의 표현식 평가

1. 수치 연산에서 쓰임

2. 너무 많은 작업이 소요되면 하지 않는다

3. 계산이 필요할때만 직접 계산을 한다

4. 수치 계산에 있어서는 지연 평가를 구현하는 데에 필요한 코딩 양이 적지 않음-> 그만큼 성능과 효율에서는 보상을 받을 수 있음

Page 33: More effective c++ 챕터3~4ppt

지연평가 방식의 정리1. 지연 평가가 만병통치약은 아님

2. 모든 계산 결과를 즉시에 사용해야 하는 경우에는 지연 평가로 얻을 수 있는 것이 없음

3. 심지어 빠른 처리에 걸림돌이 되거나 메모리 사용량을 늘리기도 함-> 피하려고 했던 계산을 모두 해ㅔ야할 경우 , 지연 평가에 쓰려고 만들어 둔 자료구조마저도 조작

4. 계산은 바로 하지 않아도 되는 경우에는 지연평가의 효과를 볼 수 있음

Page 34: More effective c++ 챕터3~4ppt

항목 18 : 예상되는 계산 결과를 미리 준비하면 처리비용을 깎을 수 있다

1. 현재 요구된 것 이외에 더 많은 작업을 미리 해둠으로써 소프트웨어의 성능을 향상시킬 수 있음

2. 과도 선행 평가라고 부름

3. 기본 아이디어는 자주 요구될 것 같은 계산이 있다면 , 그 요구를 효율적으로 처리할 수 있는 자료구조를 설계하여 비용을 낮추자는 것

Page 35: More effective c++ 챕터3~4ppt

과도 선행 평가의 방법

1. 캐싱-> 이미 계산이 끝났고 또다시 사용될 것 같은 값을 저장해두고 빠르게 활용하는 것

2. 미리가져오기-> 디스크에서 데이터를 읽을 때 , 조금씩 여러번 읽는 것보다 한번에 많이 읽는 것이 더 빠름 ( 참조 위치의 근접성 ) 이 방법을 프로그램에도 적용 .

Page 36: More effective c++ 챕터3~4ppt

과도 선행 평가

1. 메모리를 많이 쓰면 속도가 빨라진다

2. 캐싱 , 미리가져오기 등등을 하려면 메모리가 그만큼 필요하지만 , 시간은 절약된다

3. 공간과 시간은 함께 절약하기 힘들다

4. 언제나 그런것만은 아니다-> 객체의 크기가 커지면 속도도 느려질 수 있다 .

Page 37: More effective c++ 챕터3~4ppt

항목 19 : 임시 객체의 원류를 정확히 이해하자

1. C++ 에서의 진짜 ‘임시 객체’는 우리 눈에 보이지 않음

2. C++ 에서의 진짜 ‘임시 객체’는 힙 이외의 공간에 생성되는 ‘이름 없는’ 객체

3. 함수 호출을 성사시키기 위해 암시적 타입 변환이 적용될때 생성-> 오직 객체가 값으로 전달될 떄 혹은 상수 객체 참조자 타입의 매개변수로 객체가 전달될 때

4. 함수가 객체를 값으로 반환할 때 생성

5. 임시 객체가 생성되고 소멸되는데 드는 비용이 프로그램의 전체 성능에 영향을 미침

Page 38: More effective c++ 챕터3~4ppt

임시 객체의 비용

1. 임시 객체의 생성과 소멸은 그리 달갑지 않은 “비용”

2. 컴파일러가 최적화를 하여 이런 비용을 줄여줌

3. 할 수 있으면 임시객체는 만들어지지 않도록 해야함

4. 즉 임시 객체가 생성될 수 있는 지점을 보는 안목이 있어야 함

Page 39: More effective c++ 챕터3~4ppt

항목 20: 반환값 최적화가 가능하게 하자

1. 객체를 값으로 반환하는 함수는 효율을록 떨어뜨림-> 보이지 않는 임시 객체의 생성 및 소멸이 이루어지기 때문

2. 객체를 값으로 반환하는 함수에 대해서는 방법이 없음

3. 반환되는 객체의 비용을 줄이는데에 초점을 기울여야 함-> 컴파일러의 최적화 도움을 받을 수 있도록

Page 40: More effective c++ 챕터3~4ppt

항목 21: 오버로딩은 불필요한 암시적 타입변환을 막는 한 방법

1. 컴파일러가 알아서 타이변환을 해 준다는 것은 어떻게 보면 편리-> 단 임시 객체의 생성은 우리가 원하지 않는 비용의 낭비 초래

2. 임시 객체에 대한 비용을 물지 않고 암시적 타입변환이 이루어지도록 애씀

Page 41: More effective c++ 챕터3~4ppt

오버로딩을 통한 임시 객체 생성을 막음

1. 오버로딩을 통해 임시 객체의 생성을 막는 기법은 연산자 이외의 함수에도 사용 가능

2. string, char*, complex 타입 등의 인자를 취하는 함수에 대해 타입별 오버로딩을 해두면 암시적 타입변환을 막을 수 있음

3. 하지만 확실한 효율향상을 장담할 수 없다면 , 함수를 오버로딩해서 쌓아두는 것은 아무 의미 없음

Page 42: More effective c++ 챕터3~4ppt

항목 22: 단독 연산자 (op) 대신에 = 이 붙은 연산자 (op =) 를 사용하는 것이

좋을 때가 있다1. 일반적으로 대입 형태 연산자는 단독 형태

연산자보다 효율적-> 단독 영태 연산자는 새 객체를 반환해야 하기 떄문 , 임시 객체를 생성하고 소멸하는 비용이 소모되지만 대입 형태 연산자는 왼쪽인자에다가 처리결과를 기록하기 떄문에 연산자의 반환값을 담을 임시 객체가 필요 없음

2. 대입 형태 연산자와 단독 형태 연산자를 동시에 제공함으로써 클래스 사용자에게 “효율과 편리성”을 판단할 기회를 제공

Page 43: More effective c++ 챕터3~4ppt

항목 23: 정 안 되면 다른 라이브러리를 사용하자 !

1. 비슷한 기능을 가진 라이브러리라도 수행 성능에서 차이를 보일 수 있음

2. 라이브러리만 바꾸어도 성능이 좋아질 수 있을 가능성이 있음

3. 라이브러리마다 특성이 있기에 잘 따져가며 라이브러리 사용-> 수행 성능 쪽에 많은 무게를 두어 설계한 라이브러리를 쓴다면 성능 속도를 증가시킬 수 있음

Page 44: More effective c++ 챕터3~4ppt

항목 24 : 가상 함수 , 다중 상속 , 가상 기본 클래스 , RTTI 에 들어가는 비용을

제대로 파악하자1. 가상 함수는 구현에 따라 성능에 영향을 미치는 것들 중 가장 대표적인 예-> 가상테이블과 가상 테이블 포인터를 사용하여 구현 (vtbl, vptr 로 표현 )

2. 관리 방법은 크게 2 가지

3. 첫 째 , 컴파일러가 vtbl 이 필요한 목적 파일마다 해당 vtbl 의 사본을 만들어 놓고 링커가 중복되는 사김본을 제거해 가면서 최종 파일에는 하나만 남겨놓는 경우

4. 두 번째 , 경험적 규칙을 써서 클래스의 vtbl 을 가질 목적 파일을 결정하는 것 ( 어떤 클래스의 인라인도 아니고 순수 가상 함수도 아닌 함수 중 가장 첫 번째 것의 정의부분을 가지고 있는 목적파일에 그 클래스의 vtbl 을 넣음 )-> 실제로 가상함수를 인라인으로 선언하는 경우가 너무 많으면 문제가 생김

Page 45: More effective c++ 챕터3~4ppt

수행 성능의 발목을 잡는 가상 함수 비용

1. 가장 가상 함수 비용이 크게 되는 원인은 인라인에서 찾을 수 있음-> 인라인이란 컴파일 도중에 , 호출 위치에 호출되는 함수의 몸체를 끼워넣음 , 가상은 호출할 함수를 런타임까지 기다려 결정

2. 가상 함수로 쓰려면 인라인 효과를 포기해야 함 ( 가상함수를 인라인 하면 안됨 )

Page 46: More effective c++ 챕터3~4ppt

RTTI 와 비용1. RTTI 는 실행 중에 객체와 클래스의 정보를 알아낼 수

있게 하는 쓸만한 기능-> 정보를 담을 비용이 들어감

2. RTTI 정보는 클래스마다 하나씩만 있으면 되겠고 , 이 정보는 어느 객체에서든지 뽑아낼 수 있을것 같지만 그렇지 않음-> 동적 타입을 정확히 뽑아낼 수 있으려면 그 타입에 가상합수가 최소한 하나는 있어야 함

3. RTTI 는 클래스의 vtbl 을 통해 구현될 수 있도록 설계-> type_info 객체의 메모리와 더불어 vtbl 에 type_info 객체에 대한 포인터가 하나 더 추가 ( 크게 부담되는 수준은 아님 )

Page 47: More effective c++ 챕터3~4ppt

C++ 만의 특징

C++ 만의 특징 객체의 크기 증가 클래스별 데이터 증가

인라이닝 감소

가상함수 네 네 네

다중상속 네 네 아니다

가상기본클래스 자주 그렇다 가끔 그렇다 아니다

RTTI 아니다 네 아니다

Page 48: More effective c++ 챕터3~4ppt

각각의 비용을 잘 파악해야 함

1. 가상 함수 , 다중 상속 , 가상 기본 클래스 , 그리고 RTTI 를 사용할 때 들음어가는 비용에 대해 제대로 이해해야 함

2. 효율적인 측면에서는 컴파일러가 해주는 것보다 나을 수는 없음