문제의 역사:
포인터는 C++에서 언어가 등장한 이후로 주요 도구 중 하나이며, 메모리 관리와 동적 구조체, 저수준 시스템 라이브러리와의 상호작용의 기초가 됩니다. 참조는 나중에 (C++ 자체가 등장하면서) 구문을 단순화하고 코드의 안전성을 높이기 위해 추가되었습니다.
문제:
메모리 작업에서의 오류는 C++에서 가장 일반적인 문제 중 하나이며, 특히 포인터를 잘못 사용할 때 (dangling pointers, memory leaks) 발생합니다. 이때 초보자는 참조를 사용할 때와 포인터를 사용할 때를 정확하게 이해하지 못하거나 두 가지가 완전히 상호 교환 가능하다고 잘못 생각할 수 있습니다.
해결책:
포인터 (T*)는 객체의 주소를 저장하는 변수로, nullptr일 수 있으며, 산술을 지원하고 동적 할당 및 해제를 허용하며, 어떤 객체를 가리키는지 변경할 수 있습니다.
참조 (T&)는 다른 존재하는 객체의 별칭입니다. 참조는 생성 시 초기화되어야 하며 "비어 있을" 수 없고 (referencing null), 산술을 지원하지 않지만, 함수 전달 시 편리하고 안전합니다.
코드 예시:
void increment_pointer(int* p) { if(p) ++(*p); } void increment_reference(int& r) { ++r; } int main() { int a = 5; increment_pointer(&a); increment_reference(a); }
주요 특징:
초기화 후 참조를 변경하여 다른 객체를 가리키게 할 수 있습니까?
아니요. C++의 참조는 상수 별칭입니다. 초기화 후에도 참조는 항상 동일한 객체를 가리키며, 포인터는 재지정할 수 있습니다.
코드 예시:
int a = 1; int b = 2; int& ref = a; // ref = b - b의 값을 할당하지만 ref는 여전히 a를 참조합니다.
"널" 참조 또는 nullptr에 대한 참조를 생성할 수 있습니까?
아니요, 표준은 존재하지 않는 객체에 대한 참조를 허용하지 않습니다. 이는 정의되지 않은 동작을 초래합니다.
예:
int* p = nullptr; // int& r = *p; - UB
int const ptr과 const int ptr의 차이점은 무엇입니까?**
int* const ptr은 int에 대한 상수 포인터입니다 (포인터는 재지정할 수 없지만, 값은 변경할 수 있습니다). const int* ptr은 상수 int에 대한 포인터입니다 (가리키는 내용은 변경할 수 없지만, 포인터는 재지정할 수 있습니다).
코드 예시:
int a = 1, b = 2; const int* ptr1 = &a; // *ptr1은 변경할 수 없으며, ptr1 = &b는 가능합니다. int* const ptr2 = &a; // *ptr2는 변경할 수 있으며, ptr2 = &b는 불가능합니다.
젊은 개발자는 포인터를 사용하여 매개변수를 전달하고 nullptr에 대한 검사를 하지 않아 오류가 발생했을 때 프로그램이 종료되었습니다.
장점:
단점:
경험 있는 개발자는 전달이 보장될 때 int&를 사용하고, nullptr일 가능성이 있을 때는 int*를 사용하며, 반드시 포인터가 null인지 체크했습니다.
장점:
단점: