본문 바로가기

프로그래밍/More Effective C++9

항목9. 리소스 누수를 피하는 방법의 정공은 소멸자이다. 이번 항목부터 리소스 누수, 예외처리에 대한 이야기가 펼쳐진다. 와~ 신난다. 본론으로 바로 들어가자. 1. 데이터를 받아서, 기록하려 한다. 2. 데이터를 파일에 저장되어 있다. 3. 파일안에는 "개" "고양이" "코끼리" ... 여러 동물들에 대한 이름과 정보가 들어가 있다. 다음과 같은 상황에서 DB를 구축한다고 하였을 때, AAA라는 추상 클래스를 생성 -> ex) "동물" AAA를 상속받은 BBB 클래스 -> ex) "개" AAA를 상속받은 CCC 클래스 -> ex) "코끼리" AAA를 상속받은 DDD 클래스 -> ex) "고양이" 라고 한다면, 다음 클래스가 대충 이해가 갈 것이다. #include #include class AAA { public: virtual void process() =.. 2011. 7. 6.
항목8. new와 delete의 의미를 정확히 구분하고 이해하자. c++에서 흔히 사용하는 new, 그리고 delete. 그안에 감춰진 비밀을 파해쳐 보자! 팍팍!!(...) std::string* ps = new std::string( "Memory~" ); delete ps;​ 다음은 흔히들 사용하는 new와 delete의 사용 예중 하나이다. 먼저 new 부터 확인해 보자. new, 보통 포인터에 메모리를 할당하는 상황에서 사용되는데, 이 연산자는 두단계를 거쳐서 일을 수행한다. 먼저, 요청한 타입의 객체를 담을 수 있는 크기의 메모리를 할당. 그 다음 생성자를 호출하여 객체 초기화를 수행하는 것이다. 이 두단계는 바꿀 수가 없다. 당연한 이치다. 여기 까지 보면, "이게 뭐?" 그래서 어쩌란건데..? 라는 의문이 들지도 모르겠지만. 중요한건 지금부터. new가 .. 2011. 6. 30.
항목7. &&, ||, 혹은 , 연산자는 오버로딩 대상이 절대로 아니다. 시작은 단축 평가 처리에 대해서 언급되어 있다. 복합적인 불린 표현식을 평가 할 때. 모든 조건을 다 보는것이 아니라. 특정 조건으로 인해 최종 결과 값이, 참 또는 거짓 이라고 판명이 났을 때. 남은 조건들을 검사하지 않고 넘어 가는 것을 말하는데. char* p; if( ( p != 0 ) && ( strlen(p) > 10 ) ) ... // 이 경우 p != 0 임이 확인 되면 strlen은 확인하지 않는다. // && 연산자 임으로 둘중 하나만 거짓이면 어차피 거짓이니까. if( ( index upperBound ) ) ... // 이 경우도 마찬가지다. // 만약 index가 lowerBound 보다 작다면, // upperBound 와의 연산.. 2011. 6. 30.
항목6. 증가 및 감소 연산자의 전위 / 후위 형태를 반드시 구분하자. 흔히 쓰는, ++, -- 연산자에 대해서 설명하고 있는 항목이다. i++이나, ++i냐, i--이냐, --i냐... 이것의 원리를 좀 알아 보고자 하는거 같다. 역시나 가장 기본은, 사용 후 더하느냐, 더한 후 사용 하느냐. 라고 보면 되겠지만 조금 자세히 파보자. 먼저 i++, ++i의 차이인데, 증가, 감소 연산자는 전위형태이든, 후위형태이든, 인자를 받지 않는(사용하지 않는) 구조이다. 그렇기 때문에 오버로딩을 하기 위해서 걸리는 매개변수의 타입이나, 갯수등으로 구별 하기가 까다로워 진 것이다. 이를 위해 약속한 것이, 전위는 그냥두고, 후위 형태는 int 타입의 인자를 받는 것으로 하자. 라고 약속하였다고 한다. 다음과 같이 말이다. #include using namespace std; class.. 2011. 4. 29.
항목5. 사용자 정의 타입변환 함수에 대한 주의를 놓지 말자 이번 항목은 타입변환에 대한 내용. 코드를 통해 문제점 부터 파악해 보자. #include using namespace std; class AAA { int m_iNum1; public: AAA( int num1 = 0, int num2 = 1 )// 단일 인자 생성자 { m_iNum1 = num1 / num2; } operator double() const; }; AAA::operator double() const { return static_cast(m_iNum1); } void main() { AAA a( 3, 2 ); double d = 0.5 * a; // 아마 본래 의도는 이런 것이겠거니.... cout 2011. 4. 28.
항목4. 쓸데 없는 기본 생성자는 그냥 두지 말자. 차암.. 이 부분은 읽으면 읽을 수록, "아. 어쩌라고 ㅋㅋ" 라는 말이 절로 나온다. 쉽게 풀어 설명하면, class AAA { public: int id; AAA( int _id ) { id = _id; } };​ 다음과 같은 클래스가 있다고 치자. 사용자는 무언가 생성할때 ID를 같이 초기화 하고 싶은것이다. 각 id는 중복 되서는 안되고, 고유의 id를 가지고 있다고 치자. 그렇기 때문에 생성할 때 id를 넣어 주는 식의 방법을 채택 하였는데, 문제는 이거다. void main() { // 잘 된다. AAA a(10); // 이런식으로 하면 잘 된다. AAA arra[] = { AAA(0), AAA(1), AAA(2), AAA(3), }; // 여기서 부터가 문제 AAA aaa; // 기본 생성자.. 2011. 4. 25.