[More Effective C++] 항목 7 ~ 8
항목 7 : &&, ||, 혹은 , 연산자는 오버로딩 대상이 절대로 아니다
- 복합적인 불린 표현식을 평가할 때 단축 평가 처리를 할 수 있다.
-
&&, 를 오버로딩 하는 것 : 단축 평가 의미구조를 함수 호출 의미구조로 대체하겠다는 의미 - 함수 호출 의미 구조가 단축 평가 의미 구조와 다른 점
- 함수 호출이 이루어질 때는 모든 매개변수를 평가한다.(단축 평가가 이루어지지 않는다.)
- 순서대로 평가된다는 보장이 없다. 단축 평가는 항상 왼쪽에서 오른쪽으로 평가한다.
- 쉼표 연산자란?
- ex) for(int i = 0, j = strlen(s)-1 ; i < j ; ++i, –j)
- 쉼표 연산자의 규칙
- 왼쪽에서 오른쪽으로 평가한다.
- 전체 표현식의 결과는 오른쪽에 있는 표현식의 값이다.
- 정적 함수 / 전역 함수로 쉼표 연산자 구현 : 인자 평가 순서를 보장할 수 없다.
- 멤버 함수로 쉼표 연산자 구현 : 여전히 순서를 보장할 수 없다.(컴파일러마다 다른 결과)
- 연산자 오버로딩의 참된 목표 : 프로그램 읽기 / 쓰기 / 이해가 좋도록 만들자!(ESTL 23)
항목 8 : new와 delete의 의미를 정확히 구분하고 이해하자
- ‘new 연산자’와 ‘operator new’의 차이
- new 연산자 : C++에서 기본으로 제공한다. sizeof처럼 동작 원리를 바꾸는 것도 불가능하다.
- 동작 »1. 요청 타입의 객체를 담을 수 있는 크기의 메모리를 할당한다.(이 동작이 operator new 함수 호출로 동작된다.) »2. 객체의 생성자를 호출하여 할당된 메모리의 객체 초기화를 수행한다.
- operator new : 객체로 담을 메모리를 할당하는 방법이다. 오버로딩이 가능하다.
- ex)
void* operator new(size_t size);
- 반환 타입 void*
- 이 함수는 초기화되지 않은 원시 메모리의 포인터를 반환한다.(초기화하고 반환해도 되지만 대개 그렇게 하지 않는다.)
- size_t 매개변수
- 할당된 메모리 크기 지정.
- 이외의 매개변수를 오버로딩 시 추가할 수 있으나 첫번째 매개변수는 항상 size_t여야 한다.
- 반환 타입 void*
- ex)
- operator new 직접 호출도 가능하다.
- ex)
void* rawMemory = operator new (sizeof(string));
- operator new는 malloc과 마찬가지로 메모리만 할당한다.
- 생성자가 어떤 것인지는 모른다 -> 객체 구실하게 하는 게 new 연산자
- 객체를 힙에 할당하는 용도로의 수단은 new 연산자 뿐이다.(생성자 호출을 임의로 사용자가 할 수 있는 방법이 없으므로)
- 메모리 지정 new : 어디선가 할당받은 미초기화 메모리가 있는 경우 객체 행세를 할 수 있도록 만들 때 쓰는 operator new의 특별판
- ex)
void* operator new(size_t, void* location) { return location; }
- 사용시 ex) new (넘겨줄 void* 값) Widget(size);
- size_t는 사용하지 않지만 무조건 넘겨줘야 하므로 포함한다.
- 사용을 원할 시 #include
- 객체 삭제와 메모리 해제 : delete 연산자와 그 내부에서 operator delete 함수를 사용한다.
- ex)
ps->~string(); // 소멸자 호출 operator delete(ps); // 메모리 해제
- 미초기화 메모리만으로 무언가를 할 때는 new / delete 연산자를 건너뛰고 operator new / delete(C++ 버전의 malloc과 free인 셈이다.)를 사용해야 한다.(생성자 / 소멸자 호출이 불필요하므로)
- 메모리 지정 new의 메모리는 절대로 delete 연산자를 쓰지 말아야 한다.
- 원칙적으로 operator new로 할당된 것이 아니기 때문.
- 소멸자 직접 호출 / 메모리 직접 해제를 통해 해체시켜주자.
- 배열의 new 연산자가 단일 객체 생성시와 다른 점
- 메모리 할당 시 operator new[]를 호출한다.(array new라고 부른다.)
- 오버로딩이 가능하다.
- operator new[]를 지원하지 않는 컴파일러 환경에서 메모리 관리 구현은 무척이나 까다롭다.(27)
- 호출하는 생성자의 갯수가 많다.(배열 요소에 대해 일일이 생성자를 호출한다.)
- 메모리 할당 시 operator new[]를 호출한다.(array new라고 부른다.)
- 배열의 delete 연산자 역시 operator delete[]를 통한다.
- new / delete 연산자가 ‘하는 일을 수행하는 방법’은 변경이 가능하지만 ‘하는 일’은 C++언어에 고정되어 있다.