@ 16. 1 ~ 17. 1/Effective C++
-
인라인 함수 언제사용하지??@ 16. 1 ~ 17. 1/Effective C++ 2015. 12. 31. 23:09
인라인 함수 함수호출비용이 면제 인라인을 남발하면 안됨..인라인 함수로 인해 부풀려진 코드는 성능의 걸림돌이 되지 쉽다. 명령어 캐시 적중률이 떨어질 가능성도 높다.. 하지만 함수의 본문이 매우짧다면 인라인 사용하면 효율이 훨씬더 좋다,, 인라인은 명시적으로 함수 앞에 inline을 붙이면 된다. inline void f() { } 이런식으로.. 그리고 대체적으로 헤더파일에 들어 있어야 하는게 맞다..이유는 대부분의 빌드 환경에서 인라인을 컴파일 도중에 수행하기 때문이다. 그런데 이것은 요청이지 명령이 아니다..즉, 컴파일러가 자신이 보기에 복잡한 함수는 절대로 인라인 확장의 대상에 넣지 않는다.(루프가 들어있다거나 재귀함수인 경우가 이런예다) 그리고 가상 함수 호출 같은것은 절대로 인라인 해주지 않는다..
-
소멸자에서 예외를 발생?@ 16. 1 ~ 17. 1/Effective C++ 2015. 12. 5. 16:06
소멸자에서 예외를 발생시킬 수 있는 클래스가 있다. 이게 무슨 상황이냐면.. 아래와 같은 클래스가 하나있다.. class DBConnection { public: static DBConnection create(); //DBConnection 객체를 반환하는 함수. void close(); //연결을 닫습니다, 이떄 실패하면 예외를 던짐 }; 보면 사용자가 DBConnetion 객체에 대해 close를 직접 호출해야하는 설계이다.(close는 종료를 뜻하지) 사용자의 망각을 사전에 차단하는 좋은 방법이라면 DBConnection에 대한 자원 관리 클래스를 만들어서 그 클래스의 소멸자에서 close를 호출하게 하면 된다! 아래 처럼! class DBConn //DBConnection 객체를 관리하는 클래스..
-
기본 대입연산자 생성조건?@ 16. 1 ~ 17. 1/Effective C++ 2015. 12. 4. 21:37
class Test { public: Test(int& _num, int& _num2) : num(_num), num2(_num2) { } private: int& num; //이것들 떄문에.. const int num2; //이것들 때문에 }; void main() { int num = 10; int num2 = 100; int num3 = 5; int num4 = 50; Test a(num, num2); Test b(num3, num4); a = b; //대입시 에러발생 } 파란색 글씨처럼 클래스내 참조나, 상수 멤버가 있다면 이걸 바탕으로 디폴트 대입연산자(기본 대입연산자) 실행되버리면 컴파일 에러가 난다. 원래 저것들(파란색)은 대입이라는 개념이 없는 것들이니까.. 이럴때는 디폴트 말고 사용자가 ..
-
클래스 생성자는 초기화가 아니다. 정적(static)객체의 종류와 방법@ 16. 1 ~ 17. 1/Effective C++ 2015. 12. 4. 21:25
생성자내에서 하는 행동들 생성자 { ~~~~~~~~~~~ } ~~ 부분에서 이뤄지는것들은 초기화가 아니라 대입이다. 초기화는 생성자중에서도 멤버 초기화 리스트를 통해서만 이뤄진다. 즉, 초기화하려면 멤버 초기화 리스트를 이용해라 책에서는 이렇게 강조한다. 무조건 기본 디폴트 생성자라고 해도 클래스내 멤버는 초기화 리스트로 초기화해라.. 생성자:생성자() : 초기화 리스트 {} 이렇게.. 정적 객체(static)는 자신이 생성된 시점부터 프로그램이 끝날 때까지 살아 있는 객체 (애초에 스택객체, 힙 기반 객체는 될 수가 없다.) 정적 객체도 비지역 정적 객체(4가지 경우)와 (1 전역객체, 2 네임스페이스 유효범위에서 정의된 객체, 3 클래스 안에서 static으로 선언된 객체, 4 파일 유효범위에서 st..
-
const 멤버 함수의 종류, const 함수내에서 수정가능한 경우@ 16. 1 ~ 17. 1/Effective C++ 2015. 12. 4. 00:31
멤버함수에 붙는 const 키워드 역활은 해당 멤버함수가 상수 객체에 대해 호출될 함수이다 라는 사실을 알려 주는 것이다. 이런 함수가 중요한 이유는? 1. 클래스의 인터페이스를 이해하기 좋게 하기 위한것. 그 클래스로 만등러진 객체를 변경할 수 있는 함수는 무엇이고, 또 변경할 수 없는 함수는 무엇인가? 사용자 쪽에서 알고 있어야 하는것.. 2. 이 키워드를 통해서 상수객체를 사용할 수 있게 하자 프로그램의 실행 성능을 높이는 핵심 기법 -> 상수 객체에 대한 참조자로 진행 * 실제 프로그램에서 상수 객체가 생기는 경우 1) 상수 객체에 대한 포인터 혹은 2) 상수 객체에 대한 참조자로 객체가 전달될때.. 단순 상수객체 변수의 상황은 거의 없다고 봐도 무방하다.. void print(const Test..
-
#define cosnt 상수변수로 바꾸기! operator[], const static, 클래스내 const, define 매크로@ 16. 1 ~ 17. 1/Effective C++ 2015. 12. 3. 21:02
const 키워드는 팔방미인이라는데.. 1. 클래스 바깥에서는 전역 혹은 네임스페이스 유효범위의 상수를 선언(정의)하는데 쓰고 const int a = 10; //헤더 파일 상단에..const 안붙이면 이곳저곳 헤더를 포함할때 난리남 2. static으로 선언한 객체에도 const을 쓸 수 있고 static const 이든 const static이든 똑같다 3. 포인터에는 포인터 자체를 또는 포인터가 가리키는 데이터를 상수로 지정할 수 있다. int* const ptr 또는 const int* ptr 둘차이는 *을 기준으로 보는데.. const int* ptr는 *기준왼쪽에 const이므로 포인터 가리키는 값 자체가 상수 /값변경불가능 주소변경가능 int* const ptr는 *기준 오른쪽에 const이..
-
항목 37 : 어떤 함수에 대해서도 상속받은 기본 매개변수 값은 절대로 변경금지@ 16. 1 ~ 17. 1/Effective C++ 2015. 1. 25. 23:56
동적타입이란 이 객체가 어떻게 동작할 것이냐를 가리키는 타입이 동적 타입이다. 기본 클래스 *ptr1 기본 클래스 *ptr2=new 파생클래스 1 기본 클래스 *ptr3=new 파생클래스 2 ptr2의 동적 타입은 파생클래스 1 ptr3의 동적 타입은 파생클래스 2 ptr1의 경우에는 동적 타입이 없다. 동적 타입은 프로그램이 실행되는 도중에 바뀔 수 있다. 근데 위에서 ptr1,ptr2,ptr3은 기본클래스에 대한 포인터로 선언되어 있기 때문에 각각의 정적 타입도 모두 기본클래스 타입이다. 가상함수는 동적으로 바인딩된다. 이 뜻은 가상함수의 호출이 일어난 객체의 동적 타입에 따라 어떤 함수가 호출될지를 결정된다는 뜼.. 근데 기본 매개변수 값이 설정된 가상함수에서 가상함수는 동적이지만 기본매개변수는 정..
-
항목 36 : 상속받은 비가상 함수를 파생클래스에서 재정의하지말것@ 16. 1 ~ 17. 1/Effective C++ 2015. 1. 25. 23:27
왜냐면 비가상 함수는 가려지기 때문이다. 예를 들어 기본클래스 *ptr=new 파생클래스 일 경우... ptr은 기본클래스에 대한 포인터 타입으로 선언되었기 때문에 ptr을 통해 호출되는 비가상 함수는 항상 기본클래스에 정의되어 있을 것이라고 결정해 버린다. 심지어 기본클래스에서 파생된 파생클래스 객체를 가리키고 있다 해도 마찬가지다. (가상함수와 반대로 객체를 가리키는 포인터 타입에 따라 좌우된다.. 가상함수는 실제 객체죠?? ㅎ)