C/C++(call by value VS call by reference)
Call by value
값을 전달하는 방법. 함수 내 매개변수의 값을 변경하지만, main 함수에서 전달했던 원본 값을 변경하지는 않는다.
void modify(int x) {
x += 1;
printf("%d\n", x); //11
}
int main() {
int a = 10;
modify(a);
printf("%d\n", a); //10
}
Call by reference
주소를 전달하는 방법. main 함수에서의 원본 변수 주소를 전달함으로써 함수 내에서 원본 변수에 접근이 가능해진다.
void modify(int* x) {
*x += 1;
printf("%d\n", *x); //11
}
int main() {
int a = 10;
modify(&a);
printf("%d\n", a); //10
}
파이썬(call by object reference)
변경 불가능한 객체(immutable object) : 정수(int), 문자열(str), 튜플(tuple) 등 객체는 함수로 객체 자체 값 변경 불가능. 새로운 객체를 생성함.(함수가 이들 객체를 인수로 받으면 함수 내에서 해당 객체의 복사본이 생성되지 않고 동일한 객체를 참조하지만 객체 자체를 변경하는 작업은 새로운 객체를 생성하게 된다.)
def modify(x):
x += 1
print(x) #11
a = 10
modify(a)
print(a) #10
변경 가능한 객체(mutable object) : 리스트(list), 딕셔너리(dict), 집합(set) 등 객체는 함수 내부에서 변경 가능. 동일한 객체를 참조하며 원본 객체도 변경된다.
def modify(lst):
lst.append(4)
print(lst) #[1, 2, 3, 4]
a = [1, 2, 3]
modify(a)
print(a) #[1, 2, 3, 4]
파이썬은 함수를 통한 int형 변수의 값을 변경하지 못하지만 다음과 같은 방법으로 우회적으로 변경할 수 있다.
1) 함수 리턴 값을 변수에 저장
def modify(x):
return x + 1 #11
a = 10
a = modify(a)
print(a) #11
2) 리스트 등 변경 가능한 객체 사용
def modify(lst):
lst[0] += 1 #11
a = [10]
modify(a)
print(a[0]) #11
3) 클래스 사용
class Number:
def __init__(self, value):
self.value = value
a = Number(10)
modify(a)
print(a.value) #11
파이썬과 C/C++을 병행하여 공부하다 보면 함수의 개념을 혼동하게 된다.
특히 파이썬을 공부하다가 C/C++을 공부하면, 파이썬 함수는 어떻게 작동했었는지 까먹게 된다.
파이썬에서 리스트, 클래스를 활용한 방법은 차치하고,
평소에 리턴값을 저장하는 방법을 많이 사용했을 것이다.
파이썬에서 리턴값을 사용하는 코드는 C/C++에서도 구현 가능하다.
그 방법은 아래와 같다.
함수 modify가 반환하는 값의 자료형을 지정해주고,
리턴값을 main함수의 a에 저장해주면 된다.
int modify(int x) {
x += 1;
return x;
}
int main() {
int a = 10;
a = modify(a);
printf("%d\n", a);
}
그러나, C/C++에서의 call by value, call by reference 방법은 리턴값을 저장하는 방법과 결이 다르다.
call by value는 입력된 값을 매개변수로 받고, 매개변수 선에서 끝나는 것이고,
call by reference는 리턴 값 저장이 아닌, 함수 작동을 통해 원본(main) 변수 값을 변경할 수 있음이 유의미하다.
각 언어에서 함수 문법의 차이점을 정확히 인지하여 공부해야 하겠다.