[ Effective C++ ] 정리 모음집
" C++ 프로그래머의 필독서, 스콧 마이어스의 Effective C++ 를 읽고 내용 요약 / 정리 "
" '값에 의한 전달', '상수객체 참조자에 의한 전달'의 동작 방식을 토대로 어느 방식을 사용할지 선택하자! "
- 기본제공 타입 및 STL 반복자, 함수 객체 타입을 제외하고는 '값에 의한 전달'보다는 '상수객체 참조자에 의한 전달'을 선호합시다. 대체적으로 효율적일 뿐만 아니라 복사손실 문제까지 막아 줍니다.
[클래스 정의 코드]
class Person { public: Person(); virtual ~Person(); ... private: string name; string address; }; ... class Student : public Person { public: Student(); ~Student(); ... private: string schoolName; string schoolAddress; }
[값에 의한 전달 코드]
bool validateStudent(Student s); Student plato; bool platoIsOK = validateStudent(plato);
- Student는 Person의 파생 클래스 임으로 Person 객체가 먼저 생성 되야 함.
- Person 복사 생성자 호출
- Person객체 안 string 객체가 두 개 있고 이 또한 생성 해줘야 함.
- string 객체 각각 복사 생성자 호출
- Student 생성 시키며 Student의 string 객체 두 개 생성
- Student 복사 생성자 호출, string 객체 각각 복사 생성자 호출
- 복사 생성 되었던 객체 소멸시 소멸자 호출
- Student, Person, string객체 4개에 대한 소멸자 호출
📢 총 비용 : 복사 생성자 6번, 소멸자 6번 호출!
- 틀린 코드도 아니며 원하는 대로 동작하지만 비용이 부담될 수 있다...
bool validateStudent(const Student&);
새로 만들어지는 객체가 없어 생성자와 소멸자가 호출되지 않음.
📢 매개변수 선언문의 const!
- validateStudent 함수를 '값에 의한 전달'로 구현 했을 때에는 어차피 사본을 전달해서 값 변화로 부터 안전했지만, 참조자를 전달할 때에는 사본이 아니기에 앞에 const를 붙여 이점을 상쇄시킴
'복사 손실' 문제가 없어진다!
- 파생 클래스 객체가 기본 클래스 객체로서 전달되는 경우 기본 클래스의 복사 생성자가 호출 되 파생 클래스 부분이 잘리는 문제가 발생
[클래스 정의 코드]
class Window { public: ... string name() const; virtual void display() const; }; class WindowWithScrollBars : public Window { public: ... virtual void display() const; };
[복사 손실 코드]
void printNameAndDisplay(Window w) { cout << w.name(); w.display(); }
- WindowWithScrollBars가 아닌 Window 객체로 생성되어 Window::display()가 호출된다.
[복사 손실 방지 코드]
void printNameAndDisplay(const Window& w) { cout << w.name(); w.display(); }
- 어떤 종류의 객체가 넘겨지더라도 복사손실 발생 X
📢 객체 크기가 작고, 복사 생성자가 비용이 크지 않을경우에도 '값에 의한 전달'이 무조건 좋지 많은 않다.