Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C/C++ 포인터 vs Java 참조: 개념부터 핵심 차이점까지 완벽 정리


C/C++의 포인터(pointer)와 Java의 참조(reference)는 모두 '무언가를 가리킨다'는 점에서 비슷해 보이지만, 실제 동작 방식과 허용 범위에는 큰 차이가 있습니다. 이 글에서는 두 개념을 예제 코드와 함께 살펴보고, 핵심 차이점을 명확하게 정리해 드립니다.

포인터(Pointer)란?

C와 C++에서 포인터는 다른 변수의 메모리 주소를 저장하는 변수입니다. 포인터를 사용하면 변수가 위치한 메모리 주소에 직접 접근할 수 있으며, 역참조(dereference)를 통해 그 주소에 저장된 값을 읽거나 수정할 수도 있습니다. 이는 저수준 메모리 제어가 가능한 C/C++의 강력한 기능 중 하나입니다.

포인터 예제 코드

#include <iostream>
using namespace std;

int main() {
    // int형 변수
    int i = 8;

    // 포인터 변수 선언
    int* pI;

    // 변수 i의 주소를 포인터에 대입
    pI = &i;

    // 변수의 값 출력
    cout << i << endl;

    // 변수의 메모리 주소 출력
    cout << pI << endl;

    // 포인터가 가리키는 값 출력
    cout << *pI << endl;

    // 포인터를 통해 변수의 값 변경
    *pI = 10;

    // 변경된 값 확인
    cout << i << endl;

    return 0;
}

실행 결과

8
0x7fee1ae7bc94
8
10

위 코드에서 볼 수 있듯이, pI는 변수 i의 메모리 주소를 담고 있으며, *pI(역참조)를 통해 원래 변수의 값을 읽거나 10으로 직접 변경할 수 있습니다.

참조(Reference)란?

Java에서 참조는 객체를 가리키는 변수로, 이를 통해 해당 객체의 속성(필드)과 기능(메서드)에 접근하고 활용할 수 있습니다. Java 개발자는 참조를 통해 객체를 다루지만, 참조 내부의 실제 메모리 주소는 외부에 노출되지 않습니다.

참조 예제 코드

public class Tester {
    public static void main(String[] args) {
        Student student = new Student();
        student.setName("Mahesh");
        System.out.println(student.getName());
    }
}

class Student {
    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

실행 결과

Mahesh

student 변수는 힙(heap) 메모리에 생성된 Student 객체를 참조하며, 이 참조를 통해 setName()getName() 메서드를 호출할 수 있습니다.

포인터와 참조의 핵심 차이점

C/C++의 포인터와 Java의 참조 사이에는 다음과 같은 중요한 차이가 있습니다.

  • Java에는 포인터 연산이 없습니다. 포인터는 메모리 주소 그 자체이며, C/C++에서는 포인터를 증감(++, --)하여 다른 메모리 주소를 가리키도록 만들 수 있습니다. 반면 Java의 참조에는 어떠한 산술 연산도 허용되지 않습니다.

  • Java에서는 포인터 조작이 불가능합니다. Java의 참조는 내부적으로 포인터를 사용하지만, 개발자가 참조 변수를 통해 기저 포인터를 직접 조작할 수 없습니다. 덕분에 Java는 더 안전하고 견고한 언어가 되었으며, 참조는 오직 유효한 객체를 가리키거나 null일 수만 있습니다.

  • Java에서는 포인터 캐스팅이 불가능합니다. C/C++에서는 int*char*로 변환하는 등 임의의 포인터 형변환이 가능하지만, Java에서는 동일한 상속 계층에 속한 객체처럼 서로 관련된 타입 간에만 형변환이 허용됩니다.

비교 요약표

구분C/C++ 포인터Java 참조
포인터 연산(증감)가능불가능
메모리 주소 직접 접근가능불가능
임의 타입 간 캐스팅가능관련 타입 간만 가능
null 허용 여부가능가능
안전성낮음 (직접 메모리 제어)높음 (JVM이 관리)

마무리

정리하면, C/C++ 포인터는 메모리 주소를 자유롭게 다룰 수 있는 강력하지만 위험이 따르는 도구인 반면, Java 참조는 내부 구현을 숨기고 객체만을 안전하게 다루도록 설계된 추상화된 개념입니다. Java가 포인터 연산, 조작, 캐스팅을 의도적으로 금지한 것은 프로그램의 안정성과 보안을 높이기 위한 언어 설계 철학이라고 할 수 있습니다.