int, float, double 등은 pass-by-value로 넘겨야하는 이유
Pass-by-value vs Pass-by-reference
C++에서 함수에 인자를 넘기는 방법은 두가지가 있다 - pass-by-value
와 pass-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가지로 의견이 갈렸습니다.
- int, float, double 같이 작은건 copy하는게 더 빠르다. 그러니 pass-by-value를 쓰자.
- 기존의
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