그런데 코드도 복잡해지고
정상과예외상황 둘다 delete를 써줘야함
유지보수는 힘들어짐
-> 스마트 포인터를 쓰면 쉽게 문제 해결
6.
생성자에서 자원을 만들고
소멸자에서해제하는 역할을 하는 더미 클래스를 만들면
예외 발생으로 리소스가 새는 일이 방지된다.
!
그런데 정작 저 생성자 소멸자에서 문제가 발생하면?
7.
생성자에서는 리소스 누수가일어나지 않게 하자.
생성자에서 예외가 발생해서 정상 생성되지 못한 객체는
소멸자가 호출이 되지도 않는다.
!
C++에서 책임안짐 프로그래머가 알아서 해야함
8.
간단한 방법
또Try catch를써서 예외를 처리해주자.
!
하지만 또 코드 복잡해지고 중복생기고 유지복수 힘들어짐…
!
!
!
스마트 포인터를 활용해보자.
!
->
!
누수 걱정 없고, 소멸자에서 직접 리소스해제하지 않아도 되고,
상수 멤버 포인터도 비상수 포인터와 똑같이 처리 가능
9.
소멸자에서는 예외가 탈출하지못하게 하자.
소멸자는 정상적으로 객체 유효범위를 벗어날때와
객체가 직접 삭제될 때와
!
예외처리 방법에 의해 객체가 소멸되는 것인데
소멸자 안에서 어떤 방법으로 소멸되려는 건지 알수가 없음
이라는데 이제는 uncaught_exception이라는
함수로 가능하다고 함
10.
예외가 소멸자에서 처리되지않고 다른곳으로 전파되 버리면
소멸자는 실행을 마치지 못한 상태로 있게된다.
도중에 terminate가 호출될수도 있다.
!
-> try catch로 예외를 묶어두자.
11.
예외 발생이 매개변수전달 혹은
가상 함수 호출과 어떻게 다른지를 이해하자.
예외를 참조로 받든(catch by reference) 값으로 받던(catch by value)
예외로 발생되는 객체에 대해 사본을 만든다.
!
아니면 유효범위를 넘는순간 소멸되 버리니…
!
-> 복사 속도…
예외 지정 (exceptionspecification) 기능은 냉철하게 사용하자
예외 지정을 하면 어떤 함수가 어떤 예외를 발생시키는지 보임
예외 지정에 일관성이 없으면 컴파일 ‘워닝’도 발생시켜줌
게다가 예외 지정 리스트에 없는 예외를 발생시키면
unexpected함수도 자동 호출해준다.
!
근데 unexpected는 terminate를 호출…
19.
템플릿에는 예외 지정하기가무의미
-> 템플릿이 받는 매개변수는 엄청 많아서
!
예외 지정이 안 된 함수를 호출할 가능성을 가진 함수는
예외 지정을 두지말자. (특히 콜백)
20.
예외지정은?
!
예외지정의 일치성 검사는부분만 해줌
예외지정 어기면 Unexpected->terminate
예외처리 코드가 있어도 예기치 않은 문제가 발생할 수 있음
!
정말 쓸건지 다시 한번 생각해보자.
21.
예외 처리에 드는비용에 대해 정확히 파악하자
try catch를 할때 try없애고 catch를 찾고 들어가고…
예외 지정 조건 한번 찾고… 등등등
사실 다 비용이 들어가는 일
22.
예외처리를 하려고 하면?
!
어떤객체가 생성 과정을 완료하였는지 체크하는 자료구조 메모리와
이 자료구조를 업데이트하는 시간이 필요
예외 처리를 안쓰면 코드 최적화에 큰 효과
!
try만 써도 코드 크기늘고 속도 잡아먹음
!
예외 지정도 try와 마찬가지로 예외 지정을 위한 코드가 생성됨
!
그런데 예외라는건 매번 실행되는게 아니여서 큰 문젠 아니나
만약 자주 예외가 발생하면?
23.
예외 비용을 최소화하려면?
!
-가능하면 예외 기능을 지원하지 않도록 컴파일 하기
-try블록과 예외지정은 꼭 필요한 부분에만 사용
-예외를 최소로 사용했는데도 예외 때문에 느려진것 같으면
프로파일링으로 예외가 정말 성능이슈인지 확인하고
예외 처리 기능이 더 효율적인 컴파일러로 바꾸라…
강조의 밑줄…
뼛속까지 잊지 말자,80-20 법칙!
“프로그램 리소스의 80%는 전체 실행 코드의 약 20%만이 사용한다”
“실행 시간의 80%는 실행 코드의 약 20%만이 소모한다”
“메모리의 80%는 실행 코드의 약 20%만이 사용한다”
“디스크 접근 회수의 80%는 실행코드의 20%가 접근한 회수이다”
“프로그램 유지보수에 들어가는 수고의 80%는 실행 코드의 20%에 집중된다”
"게임 수입의 80%는 20%기업에 집중된다"
"은자림 코드의 80%는 팀의 25%인 김ㄷㅊ에 집중된다."
여튼 80%에 집중된다.
28.
즉 실행이 집중되는곳을 찾아서
수정하면 됨
아무 곳이나 골라잡고 효율을 향상시키려고
애쓰는 것은 별 도움이 안 된다
효율 향상에 있어지연 평가(lazy evaluation)는
충분히 고려해 볼 만하다.
어떤 처리 결과가 진짜로 필요해질 때까지 그 처리를 미룬다.
lazy evaluation
31.
참조 카운팅(Reference Counting)
진짜필요해지기 전까지는 자기만의 데이터 사본을 만들지 않고,
남이 만들어 놓은 사본을 빌어다 쓰자.
!
데이터 읽기와 쓰기를 구분하기
!
지연 방식의 데이터 가져오기(Lazy Fetching)
큰 객체를 가져올때 다 가져오지 말고 필요한 것만 가져온다.
!
지연 방식의 표현식 평가(Lazy Expression Evaluation)
불필요한 수치 계산 피하기
지연 평가를 사용하면 오히려 메모리 사용이 증가할 수 있으나
계산을 바로 하지 않아도 되는 경우가 잦은 소프트웨어에 유용
32.
예상되는 계산 결과를미리 준비하면 처리비용 깎을 수 있다
상당히 자주 요구될 것 같은 계산이 있으면
그 요구를 효율적으로 처리할 수 있는
자료구조를 설계하여 비용을 낮추자
33.
캐시를 만들어서 사용하자
!
미리가져오기 (Prefetching)
요청 받은 내용말고도 바로 다음에 쓸것 같은 데이터도 같이 가져오자.
34.
임시 객체의 원류를정확히 이해하자
C++에는 힙 이외의 공간에 생성되는 이름없는 임시 객체가 존재
!
- 함수 호출을 성사시키기 위해 암시적 타입 변환이 적용될 때
- 함수가 객체를 값으로 반환 할 때
35.
함수는 스트링을 받고
주기는캐릭터배열을 주면 변환을 위한 임시 객체가 생성됨
!
해결하기 위해 설계부터 잘 하거나
타입변환이 불필요하도록 소프트웨어를 수정
36.
반환값 최적화(return valueoptimization)가 가능하게 하자
생성자 인자를 반환하면 컴파일러가 임시 객체 비용을 없애준다.
최적화를 해준다…
37.
오버로딩은 불필요한 암시적타입변환을 막는 한 방법이다.
암시적 타입변환이 문제가 되면
오버로딩해서 다 해당하게 해서 자동 변환없이
받아들이면 된다.
그래서 얼마나 좋아질까?
를 생각하자
38.
단독 연산자(op) 대신에=이 붙은 연산자(op=)를
사용하는 것이 좋을 때가 있다
x = x + y; x = x - y;
가 되면
!
X += y; x -= y;
도 될것 같지만 사용자 정의 타입이면?
당연한건 없다.
39.
연산자의 대입 형태(exoperator+=)를 사용해서
단독 형태를 구현하면 효율적이고 편리하다.
!
!
!
!
!
!
일반적으로 대입 형태 연산자는 단독 형태 연산자보다 효율적이다.
(임시객체 X) 유지보수에도 좋다.
!
40.
정 안 되면다른 라이브러리를 사용하자!
모두가 만족하는 완벽한 라이브러리는 없다.
한쪽을 중시하면 한쪽이 떨어지기 마련
!
(C++의 iostream은 C의 stdio보다 안정적이지만
속도는 느리다…)
!
만약 라이브러리가 문제가 되면
바꾸는 것도 한 방법
라이브러리의 철학에 따라…
41.
가상 함수, 다중상속, 가상 기본 클래스,
RTTI에 들어가는 비용을 제대로 파악하자
C++스펙은 하나지만
구현은 컴파일러마다 다 다르다.
!
그 구현의 차이에 큰 성능을 미치는 것중 하나가
가상함수(virtual function)
vbtl은 클래스마다 생성이되는데
클래스의 가상 함수의 개수가 많을 때에는
무시 못할 정도의 메모리 부담이 들어간다…
45.
RTTI는 실행 중에객체와 클래스의 정보를
알아낼 수 있게 하는 꽤 쓸만한 기능
!
그런데 이 정보는
type_info라는 타입 의 객체에 저장하고,
이 type_info 객체는 type_id 연산자를 써서 액세스할 수 있다.
값은 vbtl의 인덱스 0번째에 저장 된다.
type_info와 vbtl에 포인터 하나 추가되지만
메모리 걱정할 필요는 없다…
46.
C++만의 특징 객체의크기 증가 클래스별 데이터
증가
인라이닝 감소
가상 함수 Y Y Y
다중상속 Y Y N
가상 기본 클래스 자주 가끔 N
RTTI N Y N
이런 특징들이 ‘지원되지 않는’ 환경에서 ‘꼭’ 써야 한다면
직접 구현해서 쓰세요…(정말 잘 만들수 있을까?)
!
직접 구현하는 것이 더 편할 상황이 오는데…
(정말 잘 만들수 있을까?)
가상 함수, 다중 상속, 가상 기본 클래스 RTTI에 들어가는 비용