- 모든 생성자는 객체의 올바른 초기화를 보장해야 한다.
- 반복자가 구현된 컨테이너 또는 클래스에서 요소의 개수를 구하기 위해 size 변수를 따로 선언하지 않아도 된다.
=> end와 begin의 차(subtraction)를 통해 구할 수 있고 그 타입은 std::ptrdiff_t 이다.
- explicit 키워드는 단일 인수를 가진 생성자의 정의에서 사용 가능하며 자동 형변환을 통한 생성자 호출을 막고 명시적으로만 호출하도록 한다.
- 책에선 형식 정의할 때 typedef를 사용하지만 되도록 using 키워드를 사용하자
- 멤버 함수가 아닌 연산자 오버로딩을 할 경우 첫 번째 인수가 왼쪽 피연산자에 바인딩되고 두 번째 인수가 오른쪽 피연산자에 바인딩된다.
- 멤버 함수로 연산자를 오버로딩할 경우 연산자를 호출한 객체가 왼쪽 피연산자에 암묵적으로 바인딩된다.
- C++ 언어는 클래스 작성자가 객체의 생성, 복사, 할당, 소멸 시 동작을 제어할 수 있다.
- 생성자에서 자원을 사용한다면(동적할당) 복사 생성자, 할당 연산자, 소멸자를 반드시 알맞게 정의해야한다.
- 디폴트 복사 생성자는 얕은 복사 (shallow copy)를 하기 때문에 우리가 원하는 대로 동작하지 않는다.
따라서 깊은 복사 (deep copy)를 하기 위해선 우리가 직접 복사 생성자를 알맞게 재정의 해주어야 한다.
- 얕은 복사란 새로운 객체에 기존 객체를 복사하지만 자기 자신을 그대로 참조로 반환하기 때문에 새로운 객체나 기존 객체나 똑같은
메모리 공간을 가리키게 된다. 때문에 복사된 객체를 수정하면 원치 않게 기존 객체 또한 수정이 된다.
따라서 객체를 저장할 공간을 새로 생성하되, 기존 객체를 그대로 대입하는 것이 아닌 다른 메모리 공간에 생성 후 그 메모리 공간을 가리키도록 한다. 이것을 깊은 복사라고 한다.
- 할당 연산자는 이미 존재하던 객체가 가리키는 메모리 공간을 해제 후 피연산자 객체를 할당하는 것이고, 복사 생성자는 존재하던 객체가 아닌 새로운 객체 생성과 동시에 기존 객체를 복사하여 객체를 생성하는 일종의 초기화 개념이다.
- 할당 연산자를 정의할 경우 반드시 자가 할당 여부를 확인해야 한다.
- 자가 할당(Self-assignment)는 객체를 자신에게 할당하는 것을 말한다. 자가 할당 시 할당 연산자가 자가 할당을 올바르게 처리하도록 하는 것은 중요하다. 우변이 자기 자신(this)이라면 this 포인터가 가리키는 현 객체인 *this를 반환하고 자신이 아닐 경우 좌변이 가리키던 메모리 공간을 해제 후 우변의 객체를 복사한다.
- 함수에서 참조나 어떤 값을 반환할 때 함수가 종료되면 사라지는 지역 범위의 대상을 반환하지 않도록 해야 한다.
- 할당과 초기화는 다른 개념이다. 초기화는 새로운 객체를 선언과 동시에 할당하는 것이며 = 기호를 통해 초기화하지만 할당연산자 = 가 아닌 복사 생성자를 호출하는 것이다.
반대로 할당은 이미 초기화된 객체에 '=' 연산자를 통한 복사이며 operator= 함수를 호출하는 것이다.
operator= 는 할당 전에 이전 값을 제거하지만 초기화는 이러한 사전 동작을 하지 않는다.
아래 코드에서 1~3라인은 초기화이며 4라인과 같은 코드는 할당 연산자가 호출된다.
string str = "Hello world"; // 초기화
string spaces(str.size(), ' '); // 초기화
string y; // 초기화
y = str; // 할당
- 클래스 타입을 반환하는 함수를 호출하여 객체에 할당할 경우 다음과 같은 과정을 거친다.
1. 반환할 클래스 타입의 객체를 복사 생성자를 통해 생성하여 함수를 호출한 임시 공간에 저장한다.
2. 할당 연산자를 이용하여 임시 공간에 저장된 객체를 왼쪽 피연산자에 할당한다.
- 지역 범위에서 생성된 객체는 범위를 벗어나면 소멸되고, 동적으로 할당된 객체는 객체를 가리키는 포인터를 삭제할 때 소멸된다.
- 따라서 소멸자는 생성자를 통해 할당된 객체의 메모리 공간을 해제해주어야 한다.
- 디폴트 소멸자는 포인터가 가리키는 객체의 메모리 공간을 해제하지 않는다. 포인터만 소멸되고 가리키던 객체는 남아있을 것이며 이는 메모리 누수로 이어진다. 따라서 클래스 설계자는 소멸자에서 메모리 해제를 반드시 구현해 줄 필요가 있다.
- T 클래스의 객체가 컴퓨터 자원의 처리 제어를 위해선 다음과 같은 코드가 필요하다.
T::T() // 생성자
T::~T() // 소멸자
T::T(const T&) // 복사 생성자
T& T::operator=(const T&) // 할당 연산자
각 함수를 역할에 알맞게 오버로드 해주어야 한다.
'Etc' 카테고리의 다른 글
[MarkDown] .md 파일 제목 타입 표시하기 (0) | 2020.02.28 |
---|---|
[MarkDown] .md파일에 소스 코드 영역 지정하기 (코드 하이라이트) (0) | 2020.02.27 |
유용한 커맨드 명령어 (윈도우) (0) | 2019.12.06 |
Docker toolbox 설치 Docker Quickstart Terminal vm관련 오류 (0) | 2019.11.29 |
파일 입출력 다루기. <fstream> std::ifstream, std::ofstream (0) | 2019.11.27 |
댓글