C++/Effective C++

항목 20 '값에 의한 전달'보다는 '상수객체 참조자에 의한 전달'방식을 택하는 편이 대개 낫다

멍청이 개발자 2024. 1. 20. 21:01
반응형

사실 값에 의한 전달보다 상수객체 참조자에 의한 전달 방식을 사용하라는 것은 이미 많이 들어서 알것이다. 하지만 나는 여기서 값에 의한 전달을 했을때 복사 비용이 커서 문제가 된다고만 생각을 했었는데 그 뿐만이 아니었다. 아래 코드를 한 번 보자.

class Window { // 윈도우를 나타내는 기본 클래스
public:
    ... 
    virtual void display() const; // window를 그림
};

class WindowWithScrollBars: public Window {
public:
    ...
    virtual void display() const; // 스크롤 바가 있는 윈도우를 그림
};

void DrawAnyWindow(Window w)
{
    w.display();
}

자 이런식으로 Window라는 기본 클래스를 상속하는 WindowWithScrollBars라는 클래스가 있고 또한 Window객체를 받아 윈도우를 화면에 그려주는 DrawAnyWindow라는 함수가 있다. 주의할 점은 여기서 값에 의한 전달로 window를 넘겨받는다는 것이다. 이때 만약 우리가 이런식으로 코드를 짜면 어떻게 작동할 까?

WindowWithScrollBars wwsb;
DrawAnyDisplay(wwsb);

자 여기서 문제의 '복사 손실'이 발생한다 WindowWithScrollBars는 복사되면서 Window객체가 되어버린다. 즉, WindowWithScrollBars의 구실을 할 수 없게 된다. 그래서 DrawAnyDisplay에서 호출하는 display함수는   WindowWithScrollBars의 것이 아니라 Window의 것이다. 그래서 만약 상수 객체 참조에 의한 전달로 매개변수를 받게되면 참조자는 내부적으로 포인터를 써서 구현되기 때문에 이런 복사손실이 발생하지 않는다. 

 

또한 한 가지 주의해야 할 점은 복사 비용이 작다고 해서 무작정 값에 의한 전달로 보내서는 안된다는 것이다. 만약 int, double과 같은 기본 타입은 참조자를 이용하는 것보다 값에 의한 전달을 하는것이 훨씬 이득이다. 하지만 크기는 int나 double처럼 멤버의 데이터 크기가 작아 클래스의 크기가 int나 double만큼 작다고 하더라도 값에 의한 전달을 하면 안된다. int나 double같은 것은 크기가 작고 기본 타입 이어서 레지스터에 담기지만 크기가 int, double만큼 작은 사용자 정의 클래스는 레지스터에 넣어주지 않는다. 그러므로 기본제공 타입이 아닌 이상 왠만하면 상수 객체 참조자로 전달을 하도록 하자.

 

진짜 마지막으로 한 가지 더 보태자면 STL반복자나 함수 객체는 값에 의한 전달을 하도록 하자. 예전부터 반복자와 함수객체는 값으로 전달되도록 설계되어 왔기 때문이다.

반응형