언어/C++

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

2020. 1. 20. 22:57
반응형

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

 

기본적으로 C++는 함수로부터 객체를 전달받거나 함수에 객체를 전달할 때 '값에 의한 전달' 방식을 사용합니다. 특별히 다른 방식을 지정하지 않는 한, 함수 매개변수는 실제 인자의 '사본'을 통해 초기화되며, 어떤 함수를 호출한 쪽은 그 함수가 반환한 값의 '사본'을 돌려받습니다. 이들 사본을 만들어내는게 복사 생성자 입니다. 이 점 때문에 '값에 의한 전달'이 고비용의 연산이 되기도 합니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Person {
public :
    Person();
    virtual ~Person();
    ...
 
private :
    std::string name;
    std::string address;
};
 
class Student : public Person {
public :
    Student();
    ~Student();
    ...
 
private :
    std::string schoolName;
    std::string schoolAddress;
};
 

 

이제 아래의 코드를 봐 주세요. validateStudent라는 함수를 호출하고 있는데, 이 함수는 Student 인자를 전달받고 이 인자가 유효화됐는가를 알려 주는 값을 반환합니다.

 

1
2
3
4
5
bool validateStudent (Student s);                    // Student를 값으로 전달받는 함수
 
Student plato;
 
bool platoIsOk = validateStudent (plato);            // 이제 함수를 호출합니다.
 

 

위 코드는 Student 객체를 값으로 전달하는데 비용으로 생성자 여섯 번에 소멸자를 여섯 번 사용했습니다.

Student 복사 생성자 호출 한 번, Person 복사 생성자 호출 한 번, String 복사 생성자 호출이 네 번 입니다.

 

이러한 낭비를 줄일 수 있는 방법이 있습니다. 상수객체에 대한 참조자로 전달하게 만드는 것입니다.

 

1
bool validateStudent (const Student& s);
 

 

이렇게 하면 새로 만들어지는 객체 같은 것이 없기 때문에, 생성자와 소멸자가 전혀 호출되지않는 효율적인 코드로 변합니다.

참조에 의한 전달 방식으로 매개변수를 넘기면 복사손실 문제가 없어지는 장점도 있습니다.

 

1
2
3
4
5
6
7
8
9
10
11
12
class Window {
public :
    ...
    std::string name() const;
    virtual void display() const;
};
 
class WindowWithScrollBars : public Window {
public :
    ...
    virtual void display() const;
};
Colored by Color Scripter
 

 

이제 이것을 가지고 어떤 윈도우의 이름을 출력하고 그 윈도우를 화면에 표시하는 함수를 하나 만들어 보겠습니다. 우선 틀리게 구현한 버전을 가지고 이야기를 시작하죠.

 

1
2
3
4
5
void printNameAndDisplay(Window w)            // 매개변수가 복사손실에 당하고 맙니다!
{
    std::cout << w.name();
    w.display();
}
Colored by Color Scripter
 

 

복사손실 문제에서 도망가려면, w를 상수객체에 대한 참조자로 전달하도록 만들면 됩니다.

 

1
2
3
4
5
void printNameAndDisplay(const Window& w)            // 이제 매개변수는 잘리지 않습니다.
{
    std::cout << w.name();
    w.display();
}
Colored by Color Scripter
 

 

C++ 컴파일러의 동작 원리에 관심 있는 분이라면, 참조자는 보통 포인터를 써서 구현된다는 사실을 알고 계시거나 알아내실 겁니다. 즉, 참조자를 전달한다는 것은 결국 포인터를 전달한다는 것과 일맥상통한다는 이야기죠. 이렇게 따져 보면, 전달하는 객체의 타입이 기본제공 타입일 경우에는 참조자로 넘기는 것보다 값으로 넘기는 편이 더 효율적일 때가 많습니다. 이 점은 STL의 반복자와 함수 객체에도 마찬가지입니다.

 

결론적으로, '값에 의한 전달'이 저비용이라고 가정해도 괜찮은 타입은 기본제공 타입, STL 반복자, 함수 객체 타입, 이렇게 세 가지 뿐입니다. 이 외의 타입에 대해서는 이번 항목에 나온 이야기를 따르시는 것이 좋습니다.

 

꼭 잊지 말아야 할 것!

1. '값에 의한 전달'보다는 '상수 객체 참조자에 의한 전달'을 선호합시다. 대체적으로 효울적일 뿐만 아니라 복사손실 문제까지 막아 줍니다.

2. 이번 항목에서 다룬 법칙은 기본제공 타입 및 STL 반복자, 그리고 함수 객체 타입에는 맞지 않습니다. 이들에 대해서는 '값에 의한 전달'이 더 적절합니다.

반응형

'언어 > C++' 카테고리의 다른 글

[Effective C++] 데이터 멤버가 선언될 곳은 private 영역임을 명심하자  (0) 2020.01.22
[Effective C++] 함수에서 객체를 반환해야 할 경우에 참조자를 반환하려고 들지 말자  (0) 2020.01.21
[Effective C++] 클래스 설계는 타입 설계와 똑같이 취급하자  (0) 2020.01.19
[Effective C++] 인터페이스 설계는 제대로 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 하자  (0) 2020.01.18
[Effective C++] new로 생성한 객체를 스마트 포인터에 저장하는 코드는 별도의 한 문장으로 만들자  (0) 2020.01.17
'언어/C++' 카테고리의 다른 글
  • [Effective C++] 데이터 멤버가 선언될 곳은 private 영역임을 명심하자
  • [Effective C++] 함수에서 객체를 반환해야 할 경우에 참조자를 반환하려고 들지 말자
  • [Effective C++] 클래스 설계는 타입 설계와 똑같이 취급하자
  • [Effective C++] 인터페이스 설계는 제대로 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 하자
지나가던 개발자
지나가던 개발자
지나가던 개발자
나의 발전을 위한 공간
지나가던 개발자
전체
오늘
어제
  • 분류 전체보기 (221)
    • 언어 (86)
      • C++ (43)
      • JAVA (43)
    • 게임 개발 (4)
      • 간단한 RPG 게임 만들기 (4)
      • 게임 개발 이슈 해결 (0)
    • 백준 문제풀이 (36)
      • PLATINUM (0)
      • GOLD (13)
      • SILVER (21)
      • BRONZE (2)
    • 프로그래머스 문제풀이 (32)
      • LEVEL 5 (0)
      • LEVEL 4 (0)
      • LEVEL 3 (7)
      • LEVEL 2 (19)
      • LEVEL 1 (6)
    • SQL 문제풀이 (15)
      • 프로그래머스 (4)
      • 해커랭크 (11)
    • 디자인 패턴 (1)
    • 웹 (17)
      • 웹 이론 정리 (17)
    • CS 지식 (28)
      • 알고리즘 (0)
      • 데이터베이스 (11)
      • 자료구조 (0)
      • 네트워크 (7)
      • 그래픽스 (0)
      • 운영체제 (9)
      • 기타 (1)
    • Git (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록
  • 깃 허브

공지사항

인기 글

태그

  • c++
  • 객체 생성과 파괴
  • Silver 3
  • 설계 및 선언
  • Level 2
  • Chapter 4
  • 열거 타입과 애너테이션
  • Chapter 6
  • java
  • 객체 지향 설계
  • 소멸자 및 대입 연산자
  • mysql
  • 클래스와 인터페이스
  • 프로그래머스
  • Gold 5
  • 상속
  • 백준
  • BOJ
  • level 1
  • 해커랭크

최근 댓글

최근 글

hELLO · Designed By 정상우.
지나가던 개발자
[Effective C++] '값에 의한 전달'보다는 '상수객체 참조자에 의한 전달' 방식을 택하는 편이 대개 낫다
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.