🔍 Call by Value와 Call by Reference 정리
구분 Call by Value (값에 의한 호출) Call by Reference (참조에 의한 호출)
정의 | 실제 값의 복사본을 함수에 전달 | **변수의 참조(주소)**를 함수에 전달 |
동작 | 함수 내부에서 값을 바꿔도 원본은 유지 | 함수 내부에서 값을 바꾸면 원본도 바뀜 |
안전성 | 원본 데이터 보호 | 원본이 변경될 수 있음 (주의 필요) |
예시 | int x = 5; foo(x); → x는 그대로 5 | int[] arr = {1}; foo(arr); → arr 변경됨 |
🔧 코드 예시 (Java 기준)
// Call by Value
void changePrimitive(int a) {
a = 100;
}
int x = 10;
changePrimitive(x);
// x는 여전히 10
// Call by Reference 처럼 보이지만 사실은 객체의 참조값을 "값"으로 전달 (Call by Value of reference)
void changeArray(int[] arr) {
arr[0] = 100;
}
int[] nums = {1, 2, 3};
changeArray(nums);
// nums[0]은 100으로 바뀜
Java는 항상 Call by Value입니다. 단, 객체의 참조 값(reference)을 값으로 전달하기 때문에 마치 참조 호출처럼 보일 뿐입니다.
🧠 자주 쓰이는 언어별 함수 호출 방식
언어 기본 방식 설명
C | Call by Value | 포인터를 이용해 간접적으로 Call by Reference 구현 가능 |
C++ | 둘 다 지원 | 참조(&)를 이용하면 Call by Reference 가능 |
Java | Call by Value (of reference) | 객체 참조값을 복사해서 전달 |
Python | Call by Object Reference (이름에 의한 전달) | 변수는 객체를 참조하고, 객체 자체는 변경 가능 (mutable/immutable 차이 중요) |
JavaScript | Call by Value | 원시값은 값 복사, 객체는 참조값 복사 |
Go | Call by Value | 모든 값은 복사됨, 포인터 사용으로 참조처럼 처리 가능 |
Ruby | Call by Value of reference | 객체의 참조를 값으로 넘김 (Java와 유사) |
Swift | 기본적으로 Call by Value | inout 키워드로 Call by Reference처럼 사용 가능 |
💡 Python 예시 (mutable vs immutable 중요)
# immutable
def foo(x):
x = x + 1
a = 10
foo(a)
# a는 그대로 10
# mutable
def bar(lst):
lst[0] = 999
b = [1, 2, 3]
bar(b)
# b는 [999, 2, 3]
- int, str, tuple 등은 immutable → 값이 바뀌지 않음
- list, dict, set 등은 mutable → 함수에서 바뀌면 원본도 바뀜
✅ 정리 요약
- Call by Value: 값만 복사 → 원본 불변
- Call by Reference: 주소 전달 → 원본 변형 가능
- Java / Python / JavaScript 등은 참조값을 값으로 전달 (Call by value of reference) → 헷갈리기 쉬움
- Python은 mutable vs immutable에 따라 결과 달라짐