포인터와 참조자 (Pointer & Reference)
1. 포인터 기본
포인터는 메모리 주소를 저장하는 변수입니다. *
를 사용하여 포인터를 선언하고, &
를 사용해 변수의 주소를 얻습니다.
#include <iostream>
using namespace std;
int main() {
int num = 10;
int* p = # // num의 주소를 저장
cout << "num의 값: " << num << endl;
cout << "포인터 p가 가리키는 값: " << *p << endl;
cout << "p의 주소 값: " << p << endl;
return 0;
}
📌 Tip:
*p
는 포인터가 가리키는 메모리의 값을 의미합니다. 이를 '역참조(dereference)'라고 합니다!2. 참조자 (Reference)
참조자는 변수의 별칭(Alias) 역할을 합니다. &
를 사용하여 선언하며, 실제 메모리를 공유합니다.
#include <iostream>
using namespace std;
int main() {
int a = 5;
int& ref = a; // a를 참조
ref = 10; // ref를 변경하면 a도 변경됨
cout << "a의 값: " << a << endl;
cout << "ref의 값: " << ref << endl;
return 0;
}
⚠️ 주의: 참조자는 반드시 선언과 동시에 초기화해야 합니다!
3. 포인터와 배열
배열의 이름은 배열의 첫 번째 원소를 가리키는 포인터처럼 동작합니다.
#include <iostream>
using namespace std;
int main() {
int arr[3] = {10, 20, 30};
int* p = arr; // 배열의 첫 번째 요소를 가리킴
cout << "p[0]: " << p[0] << endl;
cout << "p[1]: " << p[1] << endl;
cout << "p[2]: " << p[2] << endl;
return 0;
}
📌 Tip:
p[i]
는 *(p + i)
와 같은 의미입니다. 즉, 포인터 연산으로 배열처럼 접근할 수 있습니다.4. 포인터와 함수
포인터를 함수 인자로 넘기면 원본 데이터를 직접 수정할 수 있습니다.
#include <iostream>
using namespace std;
void changeValue(int* p) {
*p = 100; // p가 가리키는 값을 변경
}
int main() {
int num = 5;
changeValue(&num); // num의 주소 전달
cout << "변경된 num: " << num << endl;
return 0;
}
⚠️ 주의: 포인터를 사용할 때는 항상 유효한 메모리 주소를 다루어야 합니다! 잘못된 주소를 참조하면 프로그램이 비정상 종료될 수 있습니다.
5. 포인터 vs 참조
- 포인터는
*
과&
를 함께 사용하여 선언하고 주소를 다루며,null
이 될 수 있습니다. - 참조는
&
만 사용하고 반드시 초기화가 필요하며 null 상태가 없습니다. - 참조가 더 안전하고 직관적인 코드 작성에 적합합니다.
- 포인터는 동적 메모리 제어 등 더 복잡한 작업에 유리합니다.
6. 정리 및 결론
포인터와 참조는 메모리 직접 제어 및 효율적인 코드 작성에 핵심적인 역할을 합니다.
포인터는 메모리 주소를 저장하여 다양한 위치의 데이터를 조작할 수 있으며, 참조는 변수에 별명을 붙여 간편하게 접근할 수 있게 해줍니다.
각각의 특징과 장단점을 잘 이해하고 적절한 상황에서 활용하는 것이 중요합니다. 특히 함수 인자 전달 시 포인터와 참조의 사용 차이를 이해하고 응용하면 더욱 효율적인 C++ 프로그래밍이 가능합니다.
🎯 마지막 팁:
참조는 null이 될 수 없고, 값 전달보다 빠르며 안전하므로 함수 인자로 많이 사용됩니다. 하지만 동적 할당이나 복잡한 자료구조를 다룰 때는 포인터의 유연성이 빛을 발합니다.
참조는 null이 될 수 없고, 값 전달보다 빠르며 안전하므로 함수 인자로 많이 사용됩니다. 하지만 동적 할당이나 복잡한 자료구조를 다룰 때는 포인터의 유연성이 빛을 발합니다.