매개변수(parameter)는 함수에 전달되는 값이자 함수 괄호 안에 선언된 값을 말한다.

값에 의한 호출(call by value)은 매개변수로 전달되는 변수를 모두 함수 내부에서 복사해서 함수를 실행하는 방법이다.
함수 내부에서 이 복사본이 변경되더라도 원본값은 변경되지 않는다.
#include <bits/stdc++.h>
using namespace std;
int add(int a, int b) {
a += 10;
cout << a << '\n';
return a + b;
}
int main(){
int a = 1;
int b = 2;
int sum = add(a, b);
cout << a << '\n';
return 0;
}
/*
11
1
*/
함수 내부에는 11이 찍히지만 원본 변수인 main() 함수의 a는 수정되지 않는다.
vector를 값에 의한 호출을 하면 다음과 같이 된다. vector를 넘겨서 수정해도 아무런 반영이 되지 않는다.
#include <bits/stdc++.h>
using namespace std;
vector<int> v(3, 0);
void go(vector<int> v) {
v[1] = 100;
}
int main(){
go(v);
for (int i : v) cout << i << '\n';
return 0;
}
/*
0
0
0
*/
참조에 의한 호출(call by reference)은 “변수의 주소”를 매개변수로 함수에 전달하는 방법이다.
함수 내부에서 해당 매개변수를 변경하게 되면 실제 원본변수에도 반영이 된다.
다음 코드는 매개변수로 &a를 넘겼고 해당 함수에서 a를 수정했고 이게 원본 함수에도 반영된 모습이다.
#include <bits/stdc++.h>
using namespace std;
int add(int &a, int b){
a += 10;
cout << a << '\n'; return a + b;
}
int main(){
int a = 1;
int b = 2;
int sum = add(a, b);
cout << a << '\n';
return 0;
}
/*
11
11
*/
vector를 참조에 의한 호출 한 것도 마찬가지다.
#include <bits/stdc++.h>
using namespace std;
vector<int> v(3, 0);
void go(vector<int> &v) {
v[1] = 100;
}
int main(){
go(v);
for (int i : v) cout << i << '\n';
return 0;
}
/*
0
100
0
*/
primitive한 타입, 예를 들어 double, int 등은 '값에 의한 호출'로 넘기는 게 좋다. 복사가 일어나지만 간단하기 때문에 복사에 대한 코스트가 크지 않다.
하지만 reference한 타입 중 복잡한 struct나 많은 요소를 가진 배열을 배열이 차지하는 메모리가 많을 때는 참조로써 매개변수를 넘기는 게 좋다. 왜냐하면 참조없이 전달하게 될 경우 전체 복사를 해야 하는데 이 때 드는 코스트가 더 크기 때문이다.
c.f 여기서 코스트란 해당 복사에 드는 CPU 시간, 메모리를 말한다.
참조에 의한 호출이던, 값에 의한 호출이던 그 이후에 로직 자체가 배열을 복사하는 로직이라면 굳이 참조에 의한 호출을 하는 것과 값에 의한 호출을 하는 것의 차이는 사라진다.