ppotatoG


Back to all posts

Call by value vs Call by reference

Written by ppotatoG & Posted on July 26th, 2023

Call by value vs Call by reference in C

Call by value

값에 의한 호출

함수 호출 시 넘기는 인자의 값이 매개변수에 복사되는 것을 값에 의한 호출이라고 한다.

이 방법은 함수 내에서 매개변수의 값에 어떤 조작을 가하더라도 원래 변수에는 전혀 영향을 주지 않는다.

이를 통해 함수 내부에서의 로직 처리가 외부의 변수에 영향을 미치지 않도록 할 수 있다.

#include <stdio.h>
void call_by_value(int x) {
x = 100;
}
int main() {
int a = 10;
call_by_value(a);
printf("%d\n", a); // Outputs: 10
return 0;
}

call_by_value 함수 내에서 변수 x의 값을 변경해도 원본 변수 a의 값은 변경되지 않는다.

왜냐하면, 함수 호출 시 a의 값이 x로 복사되었기 때문.


Call by reference

참조에 의한 호출

Call by reference도 인자의 값이 매개변수에 복사(Copy)된다는 점은 동일하다.

다만, 참조에 의한 호출에서는 변수의 주소값이 매개변수로 넘어가게 된다.

따라서, 함수 내에서 이 매개변수를 통해 직접 변수의 값을 변경할 수 있다.

#include <stdio.h>
void call_by_reference(int *x) {
*x = 100;
}
int main() {
int a = 10;
call_by_reference(&a);
printf("%d\n", a); // Outputs: 100
return 0;
}

call_by_reference 함수를 호출할 때 a의 주소값이 넘어가게 되며, 함수 내에서 이 주소에 해당하는 값이 직접 변경 된다.

결과적으로, 원본 변수 a의 값이 변경.

Call by value, Call by reference 차이 (자바에서의 Call by value, Call by reference)

 Call by ValueCall by Reference
정의함수에 값을 복사해서 전달.
복사된 값이 변경되어도 원래 값에는 영향을 주지 않음.
함수에 값의 참조 (주소)를 전달.
함수 내에서 참조가 가리키는 값이 변경되면 원래 값도 변경.
사용 경우값을 보호하고,
함수 내부에서 원래 값의 변경 없이 그 값을 사용하고 싶을 때 사용.
원래 값에 대한 변경이 필요하거나,
대용량 데이터를 효율적으로 처리하고 싶을 때 사용.

Deep Copy vs Shallow Copy in JavaScript

JavaScript 의 shallow copy, deep copy 와 C의 Call by value, Call by reference 는 조금 다른 의미를 가진다.

Deep copy

원본 객체의 값을 복사하여 완전히 새로운 객체를 생성하는것을 뜻한다.

원본 객체와 복사된 객체는 서로 다른 메모리를 가지며, 둘 중 하나를 변경해도 다른 하나에는 영향을 미치지 않는다.

const object = {0: 'a', 1: 'b'}
const b = JSON.parse(JSON.stringify(object))
b[0] = 0
object[0] // 'a'
object[0] = 'c'
b[0] // 0

또한 React와 같은 프레임워크 또는 라이브러리에서 상태의 불변성을 유지할 때 자주 사용된다.

상태 객체를 직접 수정하지 않고 새로운 객체를 생성하여 수정한 후 상태를 갱신한다.

const [state, setState] = useState({count: 0})
setState(prev => ({...prev, count: prev.count + 1}))

깊은복사를 하는 방법

  1. JSON.parse, JSON.stringify
const object = {0: 'a', 1: 'b'}
const a = JSON.parse(JSON.stringify(object))
  1. lodashcloneDeep
const object = {0: 'a', 1: 'b'}
const a = _.cloneDeep(object)

Shallow copy

원본 객체의 주소값을 참조하는 객체를 생성하기 때문에 원본 객체와 복사된 객체는 서로 같은 메모리를 공유하고 있다.

만약 원본 객체나 복사된 객체 중 하나를 변경하면, 다른 하나도 영향을 받게 된다.

const object = {0: 'a', 1: 'b'}
const a = object
a[0] = 0
object // {0: 0, 1: 'b'}
object[0] = 'a'
a // {0: 'a', 1: 'b'}

얕은 복사는 객체나 배열의 최상위 구조만 복사하므로, 내부의 객체나 배열은 복사하지 않는다.

따라서 내부 객체나 배열의 구조를 변경하지 않으면서 상위 레벨의 구조를 변경하려는 경우에는 얕은 복사를 사용한다.

const object = {0: 'a', 1: 'b', 2: {0: 'c', 1: 'd'}}
const a = {...object}
a[2][0] = 'e'
object[2][0] // 'e'
a[2][0] // 'e'

얕은복사를 하는 방법

  1. Object.assign
const object = {0: 'a', 1: 'b'}
const a = Object.assign({}, object)
  1. spread operator
const object = {0: 'a', 1: 'b'}
const a = {...object}

얕은 복사 vs 깊은 복사
 얕은 복사 (Shallow Copy)깊은 복사 (Deep Copy)
정의원본 객체의 주소값을 복사해서 새 객체를 생성.
따라서 원본 객체와 복사된 객체는 같은 메모리를 공유.
원본 객체의 값을 복사해서 완전히 새로운 객체를 생성.
원본 객체와 복사된 객체는 서로 다른 메모리를 가지며, 이 둘은 서로에게 영향을 주지 않음.
사용 경우객체의 상위 레벨만 복사하고 싶을 때 사용.
주로 메모리 사용량을 최소화하고자 할 때 유용.
객체의 모든 레벨(상위 레벨과 하위 레벨)을 복사하고 싶을 때 사용.
주로 원본 데이터를 보존하면서 복사본에서 변경을 가하고 싶을 때 유용.

참고

[C, C++] Call by value, Call by reference 쉽게 이해하기

Call by value, Call by reference 차이 (자바에서의 Call by value, Call by reference)

JavaScript의 얕은 복사와 깊은 복사

얕은 복사 vs 깊은 복사


C와 JavaScript 에서 Call by value, Call by reference, Shallow Copy, Deep Copy의 주요 차이점

CJavaScript
Call by value값 자체를 복사해서 함수에 전달. 원본 변수에는 영향을 주지 않음.원시 타입(숫자, 문자열, 불리언 등)은 값을 복사해서 함수에 전달. 원본 변수에는 영향을 주지 않음.
Call by reference변수의 주소를 복사해서 함수에 전달. 원본 변수를 직접 변경할 수 있음.객체는 참조를 통해 함수에 전달. 원본 객체를 직접 변경할 수 있음.
Shallow Copy지원하지 않음.객체의 주소값을 복사해서 새로운 객체를 생성. 원본 객체와 복사된 객체는 같은 메모리를 공유.
Deep Copy직접 구현해야 함. 원본 변수와 복사본이 완전히 독립적.JSON.parse(JSON.stringify(obj)) 등의 방법으로 구현. 원본 객체와 복사된 객체는 독립적.

나중에 더 찾아볼 내용 (from GPT)

  1. "Call by value"에 대한 부분에서, 원시 데이터 타입 (예: 숫자, 문자열, 불리언)에 대해 더 이야기해 볼 수 있습니다.
    JavaScript와 같은 언어에서는 원시 데이터 타입이 항상 call by value 방식으로 전달됩니다.

  2. "Call by reference"에 대한 부분에서, 참조 데이터 타입 (예: 객체, 배열, 함수)에 대해 더 이야기해 볼 수 있습니다.
    JavaScript와 같은 언어에서는 참조 데이터 타입이 기본적으로 call by reference 방식으로 전달됩니다.

  3. "Shallow copy"와 "Deep copy"에 대한 부분에서, 중첩된 객체에 대한 처리를 언급할 수 있습니다.
    Shallow copy는 객체의 최상위 레벨만 복사하고, 중첩된 객체에 대해서는 참조를 유지합니다.
    반면에 deep copy는 중첩된 객체까지 복사하여 완전히 새로운 객체를 만듭니다.
    이 차이점으로 인해 두 복사 방식이 다른 결과를 가져올 수 있습니다.


Posted on July 26th, 2023