[ Effective C++ ] 항목 20 : '값에 의한 전달' 보다는 '상수객체 참조자의 의한 전달' 방식을 택하는 편이 대개 났다

Minsu._.Lighting·2023년 11월 24일
0

[ Effective C++ ] 정리 모음집
" C++ 프로그래머의 필독서, 스콧 마이어스의 Effective C++ 를 읽고 내용 요약 / 정리 "

[핵심]

" '값에 의한 전달', '상수객체 참조자에 의한 전달'의 동작 방식을 토대로 어느 방식을 사용할지 선택하자! "

  • 기본제공 타입 및 STL 반복자, 함수 객체 타입을 제외하고는 '값에 의한 전달'보다는 '상수객체 참조자에 의한 전달'을 선호합시다. 대체적으로 효율적일 뿐만 아니라 복사손실 문제까지 막아 줍니다.

💡 C++의 객체 전달!

  • 기본적으로 C++은 함수로 부터 객체를 전달 받거나, 함수에 객체를 전달할 때 '값에 의한 전달' 방식 사용
    - C에서 물려받은 특성 중 하나
    - 복사 생성자를 통한 사본을 받거나 전달

📌 '값에 의한 전달'은 생각보다 비용이 높은 연산이 될 수 있다.

[클래스 정의 코드]

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

📌 '값에 의한 전달'이 더 적절한 경우들...

  • 기본제공 타입(int, double 등)
  • STL 반복자, 함수 객체
    - 예전부터 반복자와 함수 객체의 경우 '값에 의한 전달'로 설계 되어 왔기 때문

📢 객체 크기가 작고, 복사 생성자가 비용이 크지 않을경우에도 '값에 의한 전달'이 무조건 좋지 많은 않다.

  • 컴파일러 중에는 기본제공 타입과 사용자 정의 타입을 다르게 취급하는 것이 있다.
    - 예를 들어 타입의 하부구조가 같아도 진짜 double은 레지스터에 넣어 주지만 사용자 정의 double은 넣어주지 않음.
    - 이런 개발 환경에서는 참조에 의한 전달이 좋음(포인터는 레지스터에 들어가기 때문)
  • 사용자 정의 타입의 크기는 언제나 변화에 노출되어 있다.
    - 개발 도구의 내부 구현은 언제든 바뀔 수 있기 때문
profile
오코완~😤😤

0개의 댓글

관련 채용 정보