int, float, double 등은 pass-by-value로 넘겨야하는 이유

Pass-by-value vs Pass-by-reference

C++에서 함수에 인자를 넘기는 방법은 두가지가 있다 - pass-by-valuepass-by-reference이다.

Pass-by-value는 함수 외부의 값을 copy하며 가져온다. foo(int val1)과 같은 방식이다.

Pass-by-reference는 함수 외부의 값을 참조해서 가져온다. 기존의 C에서 pointer로 가져오는 방식을 좀 더 사용하기 쉽게 바꾼 방식이. 실제 컴파일러 내부에서는 pointer로 처리한다. foo(int& val1)과 같은 방식이다.

보통 큰 object를 함수 인자로 넘기는 경우, copy 연산을 하면 너무 큰 비용이 들기 때문에 pass-by-reference를 사용하는 것이 일반적이다. 이 부분에 대해서는 이전의 ‘Const reference를 쓰세요!’ 글에서 다룬 적이 있다.

 

Primitive type에는 pass-by-value? pass-by-reference?

최근에 팀에서 이에 대해 2가지로 의견이 갈렸습니다.

  1. int, float, double 같이 작은건 copy하는게 더 빠르다. 그러니 pass-by-value를 쓰자.
  2. 기존의 const & (i.e. pass-by-reference)를 쓰자. 이래야 const-ness도 명확하게 표현할 수 있다.

여러 의견이 오갔지만, pass-by-value를 사용하는 쪽으로 의견이 수렴되었습니다. 이유는 다음과 같습니다.

int, float과 같은 Primitive 타입은 보통 굉장히 작습니다. double, long long을 제외하면 모든 경우가 reference보다 작습니다. 그렇기 때문에 primitive type의 경우 reference를 하는 게 더 큰 비용이 들어가므로, pass-by-value를 해주는게 좋습니다.

또, pass-by-value를 하는 경우 alias를 피할 수 있기 때문에, 컴파일러의 optimizer가 더 효율적으로 작동하게 됩니다.

컴파일러에서 -O3 옵션을 걸어줄 경우, pass-by-value나 pass-by-reference 모두 같은 값으로 수렴하게 된다는 것을 확인했습니다. 대신 이 경우 각각 구현의 모습은 foo (int val1, int val2, int val3)foo (cosnt int& val1, const int& val2, const int& val3)처럼 생겼는데, 후자의 경우 예상 외로 가독성이 오히려 떨어지는 것을 볼 수 있었습니다.

출처

https://stackoverflow.com/questions/14013139/is-it-counter-productive-to-pass-primitive-types-by-reference