C++에서는 크게 값으로 전달 / 참조로 전달 하는 두 가지의 전달 방식이 있습니다.
각 전달 방식 모두 장단점과 사용해야 하는 경우,
사용하지 않아야 하는 경우가 있습니다.
C++에서 포인터가 아닌 인수는 값으로 전달 됩니다.
인수가 값으로 전달되면, 인수의 값은 해당 함수 매개 변수의 값으로 복사됩니다.
void foo(int y)
{
cout << "y = " << y << endl;
}
int main()
{
foo(5); // first call
int x = 6;
foo(x); // second call
foo(x+1); // third call
return 0;
}
첫 번재 foo(5) 호출에서 인수는 리터럴 5입니다.
foo(5)가 호출되면 변수 y가 만들어지고
값 5가 y로 복사됩니다. 변수 y는 foo() 함수가 종료되면 소멸합니다.
두 번째, 세 번째 call 도 마찬가지입니다.
즉, 인수의 복사본이 함수로 전달되므로 원래 인수는 함수 안에서 수정할 수 없습니다.
#include <iostream>
void foo(int y)
{
std::cout << "y = " << y << '\n';
y = 6;
std::cout << "y = " << y << '\n';
} // y is destroyed here
int main()
{
int x = 5;
std::cout << "x = " << x << '\n';
foo(x);
std::cout << "x = " << x << '\n';
return 0;
}
x = 5
y = 5
y = 6
x = 5
main 함수의 시작 부분에서 변수 x의 값은 5입니다.
foo(X)가 호출되면 foo의 매개변수 y에 값 5가 복사되어 전달됩니다.
foo() 함수 내부에서 y의 값은 6으로 변경되고 소멸하지만,
y가 변경되더라도 변수 x의 값은 아무런 영향을 받지 않습니다.
값으로 전달은 두 가지 한계가 있습니다.
변수를 참조로 전달하려면,
함수 매개 변수를 일반 변수가 아닌 참조로 선언해야 합니다.
void addOne(int& y)
{
y = y+1;
}
함수가 호출되면 y는 인수에 대한 참조가 됩니다.
변수에 대한 참조는 변수 자체와 똑같이 취급되므로
참조에 대한 모든 변경 사항은 인수에도 적용됩니다.
void foo(int& value)
{
value = 6;
}
int main()
{
int value = 5;
cout << "value = " << value << '\n';
foo(value);
cout << "value = " << value << '\n';
return 0;
}
value = 5
value = 6
보다시피 함수는 인수의 값을 5에서 6으로 변경했습니다.
참조를 사용하면 함수가 인수의 값을 변경할 수 있으므로 인수가 읽기 전용일 때는
사용하기에 바람직하지 않습니다. 함수가 인수의 값을 변경해서는 안되지만 값으로
전달하지 않으려면 const
참조를 전달하는 것이 가장 좋습니다.
const 참조는 변수가 참조를 통해 변경되는 것을 허용하지 않는 참조입니다.
그러므로 const 참조를 매개변수로 사용하면
함수가 인수를 변경하지 않는다는 것을 호출자에게 보장합니다.
const 참조를 사용하는 것은 다음과 같은 이유로 유용합니다.
컴파일러는 변경해서 안되는 값을 변경하지 않도록 합니다.
함수가 인수의 값을 변경하지 않는다는 것을 프로그래머에게 알려줍니다.
const가 아닌 참조 매개 변수에는 const 인수를 전달할 수 없습니다.
const 참조는 l-value, const l-value 및 r-value를 포함한 모든 유형의 인수를 허용합니다.
포인터를 참조로 전달하고,
함수가 포인터의 주소를 완전히 변경하도록 할 수 있습니다.
#include <iostream>
void foo(int*& ptr) // pass pointer by reference
{
ptr = nullptr; // 실제 ptr 인수를 변경할 수 있다.
}
int main()
{
int x = 5;
int *ptr = &x;
std::cout << "ptr is: " << (ptr ? "non-null" : "null") << '\n'; // prints non-null
foo(ptr);
std::cout << "ptr is: " << (ptr ? "non-null" : "null") << '\n'; // prints null
return 0;
}
non-const 참조는 const 값, 또는 r-value로 초기화할 수 없으므로
참조 매개변수에 대한 인수는 일반 변수여야 한다.
인수가 변경될 수 있는지는 함수 호출에서 알 수 없다.
값으로 전달이나 참조로 전달 모두 인수에서는 동일하게 보인다.
함수 선언을 보고 인수가 값으로 전달인지 참조로 전달인지 알 수 있다.
이것은 프로그래머가 함수에서 인수의 값을
변경한다는 것을 인식하지 못하는 상황을 초래할 수 있다.
참조 : 소년코딩