개발머해니

Pass By Value와 Pass By Reference : Python, Java, C 차이 본문

백엔드

Pass By Value와 Pass By Reference : Python, Java, C 차이

왕행님 2024. 2. 7. 21:36
728x90
반응형

Java


1) 기본형변수 : 값으로 전달(Pass By Value)
2) 참조형변수 : 객체주소가 전달(Pass By Reference)
기본형변수 : boolean, char, byte, short, int, long, float, double (Stack메모리에 값 저장)
참조형변수 : Integet, Boolean, String... (Stack메모리에 주소 저장, Heap메모리에 값 저장)

자바에서는 파이썬과는 달리 매개변수 전달 방식이 다릅니다. 자바에서는 모든 매개변수가 값으로 전달됩니다. 이 말은 변수가 메서드로 전달될 때, 실제 값이 전달되는 것이지 변수의 참조가 전달되는 것이 아니라는 것입니다. 따라서 자바에서는 메서드 내에서 매개변수의 값이 변경되어도 호출자에게 영향을 주지 않습니다.

그러나 참조형 변수(예: 객체)를 매개변수로 전달할 때, 그 객체의 주소(참조)가 복사되어 전달됩니다. 이 경우, 메서드 내에서 객체의 내용을 변경하면 호출자에게도 그 변경이 반영됩니다.

예를 들어, 자바에서 배열을 메서드의 매개변수로 전달하면 배열의 주소가 전달되므로 메서드 내에서 배열의 요소를 변경하면 호출자에게도 그 변경이 반영됩니다. 하지만 매개변수로 전달된 참조 변수 자체를 다른 객체로 변경하더라도 호출자에게는 영향을 주지 않습니다.

다음은 자바에서의 예시입니다:

public class Main {
    public static void main(String[] args) {
        int[] array = {1, 2, 3};
        modifyArray(array);
        System.out.println(Arrays.toString(array)); // [2, 4, 6]
    }
    
    public static void modifyArray(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            arr[i] *= 2;
        }
    }
}

 

C언어


C 언어에서는 함수에 매개변수를 전달할 때 값에 의한 호출(pass-by-value)이 기본적으로 사용됩니다. 이는 변수의 값을 복사하여 함수로 전달하므로 함수 내에서 매개변수의 값을 변경해도 호출자에게는 영향을 주지 않습니다.

그러나 포인터를 사용하여 주소(참조)를 전달할 수도 있습니다. 포인터를 통해 변수의 주소를 전달하면 함수 내에서 해당 주소의 값을 변경할 수 있으며, 이는 호출자에게도 영향을 줍니다.

예를 들어, 배열을 함수의 매개변수로 전달할 때 실제로는 배열의 첫 번째 요소의 주소가 함수에 전달됩니다. 따라서 함수 내에서 배열의 요소를 변경하면 호출자에게도 그 변경이 반영됩니다.

다음은 C 언어에서의 예시입니다:

#include <stdio.h>

void modifyArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;
    }
}

int main() {
    int array[] = {1, 2, 3};
    int size = sizeof(array) / sizeof(array[0]);
    
    modifyArray(array, size);
    
    for (int i = 0; i < size; i++) {
        printf("%d ", array[i]); // 출력: 2 4 6
    }
    
    return 0;
}

 

Python


파이썬에서는 변수를 함수에 전달할 때, 값이 아니라 객체의 참조가 전달됩니다. 이것은 C나 자바와는 약간 다릅니다.

정확하게 말하자면, 객체의 주소(참조)가 전달되는 것이 아니라 객체의 참조(즉, 메모리 상의 위치)가 전달됩니다. 이 말은 함수가 객체를 변경할 때 객체의 내용이 아니라 객체에 대한 참조가 변경되는 것입니다.

예를 들어, 다음과 같은 코드를 살펴보겠습니다:

def modify_list(my_list):
    my_list.append(4)
    my_list = [1, 2, 3]

def solution():
    a = [0]
    modify_list(a)
    print(a)  # 출력: [0, 4]

위 코드에서 a라는 리스트를 함수에 전달하면 함수 내에서 my_list라는 이름으로 그 값을 받게 됩니다. 함수 내에서 리스트에 append 메서드를 사용하여 요소를 추가한 후, my_list를 새로운 리스트로 덮어씌우면서 변경합니다. 그러나 이 변경은 a 변수에는 영향을 주지 않습니다. 이는 modify_list 함수 내에서 my_list가 새로운 리스트로 덮어씌워졌지만, 이는 함수 내에서만 적용되고 호출자의 a 변수에는 영향을 주지 않기 때문입니다.

따라서 파이썬에서는 변수를 함수에 전달할 때 값이 아니라 객체에 대한 참조가 전달되며, 이로 인해 함수 내에서 객체의 내용을 변경할 때 호출자에게 영향을 줄 수 있습니다. 하지만 변수 자체를 변경하더라도 호출자에게는 영향을 주지 않습니다.

 

파이썬에서 append와 = 차이가 뭔데?


append와 = 연산자는 리스트에 대해 다른 작업을 수행합니다.

1. append: append 메서드는 리스트에 새로운 요소를 추가합니다. 기존 리스트에 새로운 요소가 뒤에 추가되는 것이기 때문에 리스트의 크기가 늘어납니다.

my_list = [1, 2, 3]
my_list.append(4)
print(my_list)  # 출력: [1, 2, 3, 4]

2. = (할당 연산자): 할당 연산자는 변수에 새로운 값을 할당합니다. 이 때 변수가 참조하는 객체가 변경되는 것이 아니라 변수 자체가 새로운 객체를 참조하게 됩니다. 이전 객체에 대한 참조는 끊기게 됩니다.

my_list = [1, 2, 3]
my_list = [4, 5, 6]  # 새로운 리스트를 할당
print(my_list)  # 출력: [4, 5, 6]

따라서 append 메서드는 리스트의 내용을 변경하고, = 연산자는 변수가 참조하는 객체를 변경합니다. 이러한 차이로 인해 append 메서드는 원래 리스트에 새로운 요소를 추가하고, = 연산자는 변수가 새로운 객체를 참조하도록 만듭니다.

 

하지만 자바에서는?


= (할당 연산자) : 할당 연산자는 변수에 새로운 값을 할당합니다. 이 때 변수가 참조하는 객체가 변경되는 것이 아니라 변수 자체가 새로운 객체를 참조하게 됩니다. 이전 객체에 대한 참조는 끊기게 됩니다.

import java.util.ArrayList;

public class Main {
    public static void modifyList(ArrayList<Integer> myList) {
        myList.add(4);
        myList = new ArrayList<Integer>();
        myList.add(1);
        myList.add(2);
        myList.add(3);
    }

    public static void main(String[] args) {
        ArrayList<Integer> a = new ArrayList<>();
        a.add(0);
        modifyList(a);
        System.out.println(a);  // 출력: [0, 4]
    }
}

위 코드에서 modifyList 메서드는 리스트에 4를 추가한 후, 새로운 리스트를 할당하고 요소 1, 2, 3을 추가합니다. 그러나 이 변경은 호출자인 main 메서드에서의 a 변수에는 영향을 주지 않습니다. 호출자인 main 메서드에서의 a 변수는 여전히 원래의 리스트를 참조하고 있기 때문에 [0, 4]를 출력합니다.

 

출처 : ChatGPT

728x90
반응형