ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 참조변수에 대한 작은 오해
    개발/자바 2020. 3. 16. 14:33

    자바에서 기본 자료형 변수를 만들 때를 제외하고, 객체는 전부 new 연산자를 이용해 동적으로 메모리를 할당한다. new 연산자가 반환하는 것은 내부적으로는 메모리의 주소겠지만 자바에서 개발자는 메모리 주소를 알 수 없고 해싱을 거친 참조값(해시코드)만 확인할 수 있다. 애초에 자바에서는 메모리를 직접 다룰 일이 없다.

     

    참조값은 메모리 주소 정보를 갖고 있기 때문에 C/C++의 포인터와 같다고 봐도 된다. 객체를 매개변수로 넘길 때 해당 객체의 참조값이 전달되므로 함수 내에서 객체의 데이터를 변경하면 외부에서도 바뀐 결과를 확인할 수 있다. 다음의 결과는 Lee가 출력된다. changeName()의 매개변수 student는 지역변수이지만 main()에서 생성한 Student 객체의 참조값을 가지고 있으며, 함수 안에서는 해당 참조값을 통해 데이터에 접근한 것이므로 외부에도 반영이 된다.

    public class Student {
    	String name;
    	Student() {
    		name = "Kim";
    	}
    }
    public class Main {
    	private static void changName(Student student) {
    		student.name = "Lee";	
    	}
    	public static void main(String[] args) {
    		Student student = new Student();
    		changName(student);
            System.out.println(student.name);
    	}
    }

     

    여기에서 작은 오해가 생길 수 있다. 함수에서 매개변수로 받은 객체에 새로운 참조값을 할당하면 외부에도 적용될 수 있다고 생각하는 것. 다음 코드를 보자.

    public class Main {
    	private static void changStudent(Student student) {
    		student = new Student();
    		student.name = "Lee";
    	}
    	public static void main(String[] args) {
    		Student student = new Student();
    		changStudent(student);
    		System.out.println(student.name);
    	}
    }

    결과값은 Lee가 아닌 Kim이다. 함수에서 매개변수에 새로운 참조값을 할당하며 반환값이 없다. 외부에서 전달한 참조값을 저장하고 있던 student에 새로운 참조값이 대입되면 기존 참조값은 어느 누구도 접근할 수 없다. 가비지 컬렉터의 수거 대상이 되어 버린다. 매개변수인 student는 스택에 저장되는 지역변수일 뿐이므로 외부에서 접근할 길이 없다. 함수에서 매개변수의 참조값으로 데이터를 변경할 수 있는 것과 지역변수에 새로운 참조값을 할당하는 것은 전혀 다른 문제다. C/C++에서 이 문제를 해결하고 싶다면 매개변수에 이중 포인터를 넘기면 된다.

    #include <string>
    class Student
    {
    private:
    	std::string name;
    
    public:
    	Student() :name("Kim")
    	{}
    
    	void setName(std::string name)
    	{
    		this->name = name;
    	}
    
    	std::string getName()
    	{
    		return name;
    	}
    };
    
    void changeName(Student** student)
    {
    	delete *student;
    	*student = new Student();
    	(*student)->setName("Lee");
    }
    
    int main()
    {
    	Student* student = new Student();
    	printf("%s\n", student->getName().c_str());
    
    	changeName(&student);
    
    	printf("%s\n", student->getName().c_str());
    	delete student;
    
    	return 0;
    }

    '개발 > 자바' 카테고리의 다른 글

    Dynamic Web Project를 Import한 후 생긴 오류들  (0) 2020.04.25
    추상 클래스는 무엇  (0) 2020.03.19
    정렬 순서 바꾸기  (0) 2020.03.12
    배열 탐색도 연산이다  (0) 2020.03.11
    객체의 final 변수  (0) 2020.03.10

    댓글

Designed by Tistory.