Call-by-value vs Call-by-reference
Call-by-value와 Call-by-reference는 프로그래밍에서 함수에 인자를 전달하는 두 가지 주요 방법입니다.
- Call-by-value (값에 의한 호출)
- 이 방식에서는 함수에 인자를 전달할 때 인자의 실제 값의 복사본을 만들어서 함수에 전달합니다.
- 함수 안에서 인자의 값이 변경되더라도, 원본 인자에는 영향을 주지 않습니다.
- 복사본을 사용하기 때문에 메모리 사용량이 더 많을 수 있고, 큰 데이터를 전달할 때 성능적으로 비효율적일 수 있습니다.
- Call-by-reference (참조에 의한 호출)
- 참조에 의한 호출은 함수에 인자를 전달할 때 인자의 메모리 주소를 전달합니다.
- 이로 인해 함수 안에서 인자의 값을 변경하면 원본 데이터에도 영향을 미치게 됩니다.
- 메모리 주소만 전달되기 때문에 큰 데이터를 다룰 때 메모리와 성능적인 이점이 있습니다.
- 하지만 원본 데이터가 변경될 수 있으므로 프로그래밍할 때 주의가 필요합니다.
이 두 방식은 변수의 독립성과 효율성을 결정하는 데 중요한 역할을 합니다. 프로그래밍 언어에 따라 기본적으로 값을 전달하는 방식(Call-by-value)인 경우가 많고, 참조로 전달하려면 특별한 문법이나 방법을 사용해야 합니다. 예를 들어, C++에서는 참조자(reference)나 포인터(pointer)를 사용하여 참조에 의한 호출을 구현할 수 있습니다. 반면에, 자바(Java)에서는 기본형(primitive types)은 항상 값에 의한 호출로 전달되고, 객체는 참조의 값에 의해 전달되는 것처럼 보이지만 실제로는 객체의 주소를 값으로 전달하는 것입니다(이를 참조 값에 의한 호출이라고 하기도 합니다).
콜 바이 밸류는 값의 전달이라서 메모리 참조를 전달하는 거랑은 또 다른 거지 이것의 차이는 밸류 전달 방식은 같은 메모리 참조가 아니라서 관련된 인스턴스나 변수등을 변경하여도 다른 것도 변하지 않는 거고 반대로 메모리는 같은 것을 가리키기 때문에 변경되는 거고 내가 알고 있는 것이 맞나
네, 맞습니다. 여러분이 이해하고 계신 바가 정확합니다.
Call-by-value 방식에서는 함수로 전달된 값이 복사되어 새로운 메모리 공간에 저장됩니다. 이 복사된 값이 함수 내에서 변경되더라도, 그 변경이 원본 변수에 영향을 미치지 않습니다. 원본 변수와 함수 내의 변수는 서로 다른 메모리 주소를 가지고 있기 때문입니다.
반면, Call-by-reference 방식에서는 함수로 전달된 변수의 메모리 주소가 사용됩니다. 따라서 함수 내에서 해당 참조를 통해 값을 변경하면, 그 변경이 원본 변수에도 반영됩니다. 원본 변수와 함수 내의 변수는 같은 메모리 주소를 참조하기 때문입니다.
이 두 방식은 함수가 변수를 다루는 방식뿐만 아니라 프로그래머가 코드를 작성할 때 변수의 가용성과 안전성을 고려하는 데 중요한 요소입니다.
자바가 콜바이 벨류? 아님 콜 바이 레퍼런스?
자바에서 메소드 호출 방식을 이해할 때 흔히 혼란이 오는 부분입니다. 자바는 기본적으로 '콜 바이 밸류(Call-by-value)' 방식을 사용합니다. 이 말은 메소드를 호출할 때 전달되는 인자의 '값'이 복사되어 전달된다는 의미입니다.
기본 자료형(primitive types)인 int, float, double 등을 메소드에 전달하면, 그 값 자체가 복사되어 전달됩니다. 따라서 메소드 내에서 이 값들을 변경한다 하더라도 원래의 값에는 영향을 주지 않습니다.
객체 참조형 변수를 메소드에 전달할 경우에는 변수가 가리키고 있는 객체의 '참조값'이 복사되어 전달됩니다. 이 때문에 '콜 바이 레퍼런스(Call-by-reference)'처럼 보일 수 있지만, 실제로는 객체의 주소 값을 복사하는 '콜 바이 밸류'입니다. 따라서 메소드 내에서 참조형 변수를 통해 객체의 상태를 변경할 수 있지만, 참조형 변수 자체를 변경하는 것은 메소드 밖의 변수에 영향을 주지 않습니다.
예를 들어, 객체의 참조를 메소드에 전달하고, 메소드 내부에서 새로운 객체로 참조를 변경한다고 해도, 원래의 참조는 변경되지 않습니다.
간단한 예제를 통해 설명드리겠습니다:
public class CallByValueExample {
public static void main(String[] args) {
int value = 10;
modifyValue(value);
System.out.println("After modifyValue: " + value); // 값은 10이 그대로 출력됩니다.
MyObject obj = new MyObject();
modifyObject(obj);
System.out.println("After modifyObject: " + obj.data); // 객체 내부의 data 값이 변경된 것을 볼 수 있습니다.
}
public static void modifyValue(int number) {
number = 20; // 이 메소드 안에서만 number의 값이 20으로 변경됩니다.
}
public static void modifyObject(MyObject ref) {
ref.data = 50; // 객체의 'data' 필드 값을 변경합니다. 이 변경은 호출한 측의 객체에도 영향을 줍니다.
}
static class MyObject {
int data = 0;
}
}
위의 코드에서 modifyValue 메소드는 기본 자료형 변수의 값을 변경하려 하지만, 이 변경은 메소드 내부에만 국한되고 원래 변수에는 영향을 주지 않습니다. 반면 modifyObject 메소드는 객체의 상태를 변경하고, 이 변경은 호출한 측에도 반영됩니다. 그러나 이것은 참조의 복사본을 통해 일어나는 일이므로, 자바의 메소드 호출 메커니즘이 '콜 바이 밸류'임을 확인할 수 있습니다.
'[F-Lab 멘토링 학습]' 카테고리의 다른 글
| Public IP vs Private IP (0) | 2023.11.11 |
|---|---|
| 프로세스와 스레드의 차이 (0) | 2023.11.11 |
| (스터디) 파이브 라인스 오브 코드 4장 타입 코드 처리하기 (0) | 2023.11.06 |
| (스터디) 파이브 라인스 오브 코드 리뷰 1-3장 (0) | 2023.11.04 |
| 성능 최적화를 위해 어떤 방법과 도구를 사용하나요?에 대한 답변 (1) | 2023.11.04 |