C++에서 참조는 특정 변수에 대한 별칭을 제공하는 기능입니다. 참조를 사용하면 포인터보다 간결하고 직관적인 코드를 작성할 수 있습니다. 이번 포스트에서는 참조와 포인터의 기본 개념과 사용법을 다양한 예제를 통해 살펴보겠습니다.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// 첫 번째 블록: 참조와 포인터 기본 사용법
{
int num0 = 10; // 정수형 변수 선언 및 초기화
int& num1 = num0; // num0에 대한 참조 선언
int* num2 = &num0; // num0에 대한 포인터 선언
cout << num0 << endl; // 10 출력
cout << num1 << endl; // 10 출력
cout << *num2 << endl; // 10 출력
cout << endl;
num0 = 20; // num0 값 변경
cout << num0 << endl; // 20 출력
cout << num1 << endl; // 20 출력
cout << *num2 << endl; // 20 출력
cout << endl;
num1 = 30; // num1 값 변경 (num0 값 변경)
cout << num0 << endl; // 30 출력
cout << num1 << endl; // 30 출력
cout << *num2 << endl; // 30 출력
cout << endl;
*num2 = 40; // 포인터를 통해 num0 값 변경
cout << num0 << endl; // 40 출력
cout << num1 << endl; // 40 출력
cout << *num2 << endl; // 40 출력
cout << endl;
}
// 두 번째 블록: 참조의 고정성
{
int num0 = 10; // 정수형 변수 선언 및 초기화
int& num1 = num0; // num0에 대한 참조 선언
int num2 = 20; // 또 다른 정수형 변수 선언 및 초기화
// num1에 num2를 대입하면 num0의 값이 num2의 값으로 변경됨
num1 = num2; // num1은 여전히 num0을 참조하고 있음
// num1 = num2;는 num1이 가리키는 값을 num2의 값으로 변경하는 것을 의미함
}
// 세 번째 블록: 벡터 참조와 포인터
{
vector<int> vec0; // 벡터 선언
vector<int>& vec1 = vec0; // 벡터 참조 선언
vector<int>* vec2 = &vec0; // 벡터 포인터 선언
// vec1은 vec0을 참조하고, vec2는 vec0의 주소를 가리킴
}
// 네 번째 블록: 동적 메모리 할당과 참조
{
int* num0 = new int(12); // 동적으로 메모리 할당 및 초기화
int& num1 = *num0; // 동적 메모리를 참조하는 레퍼런스 선언
cout << num0 << endl; // 포인터 주소 출력
cout << num1 << endl; // 12 출력 (할당된 값)
delete num0; // 동적 메모리 해제
// 해제된 메모리를 참조하면 위험
// cout << num1 << endl; // 해제된 메모리 접근 시도 (위험)
}
// 다섯 번째 블록: 상수 포인터와 참조의 유사성
{
int num0 = 10; // 정수형 변수 선언 및 초기화
int& num1 = num0; // num0에 대한 참조 선언
int* const num2 = &num0; // num0에 대한 상수 포인터 선언
int num3 = 20; // 또 다른 정수형 변수 선언 및 초기화
// 상수 포인터는 참조처럼 초기화 후 가리키는 대상을 변경할 수 없음
// num2 = &num3; // 컴파일 오류 발생
}
}
첫 번째 블록에서는 참조와 포인터의 기본 사용법을 보여줍니다.
{
int num0 = 10; // 정수형 변수 선언 및 초기화
int& num1 = num0; // num0에 대한 참조 선언
int* num2 = &num0; // num0에 대한 포인터 선언
cout << num0 << endl; // 10 출력
cout << num1 << endl; // 10 출력
cout << *num2 << endl; // 10 출력
cout << endl;
num0 = 20; // num0 값 변경
cout << num0 << endl; // 20 출력
cout << num1 << endl; // 20 출력
cout << *num2 << endl; // 20 출력
cout << endl;
num1 = 30; // num1 값 변경 (num0 값 변경)
cout << num0 << endl; // 30 출력
cout << num1 << endl; // 30 출력
cout << *num2 << endl; // 30 출력
cout << endl;
*num2 = 40; // 포인터를 통해 num0 값 변경
cout << num0 << endl; // 40 출력
cout << num1 << endl; // 40 출력
cout << *num2 << endl; // 40 출력
cout << endl;
}
두 번째 블록에서는 참조가 초기화 후 다른 변수를 가리킬 수 없음을 보여줍니다.
{
int num0 = 10; // 정수형 변수 선언 및 초기화
int& num1 = num0; // num0에 대한 참조 선언
int num2 = 20; // 또 다른 정수형 변수 선언 및 초기화
// num1에 num2를 대입하면 num0의 값이 num2의 값으로 변경됨
num1 = num2; // num1은 여전히 num0을 참조하고 있음
// num1 = num2;는 num1이 가리키는 값을 num2의 값으로 변경하는 것을 의미함
}
세 번째 블록에서는 벡터를 참조와 포인터로 다루는 방법을 설명합니다.
{
vector<int> vec0; // 벡터 선언
vector<int>& vec1 = vec0; // 벡터 참조 선언
vector<int>* vec2 = &vec0; // 벡터 포인터 선언
// vec1은 vec0을 참조하고, vec2는 vec0의 주소를 가리킴
}
네 번째 블록에서는 동적 메모리 할당과 참조의 사용법을 설명합니다.
{
int* num0 = new int(12); // 동적으로 메모리 할당 및 초기화
int& num1 = *num0; // 동적 메모리를 참조하는 레퍼런스 선언
cout << num0 << endl; // 포인터 주소 출력
cout << num1 << endl; // 12 출력 (할당된 값)
delete num0; // 동적 메모리 해제
// 해제된 메모리를 참조하면 위험
// cout << num1 << endl; // 해제된 메모리 접근 시도 (위험)
}
다섯 번째 블록에서는 상수 포인터와 참조의 유사성을 설명합니다.
{
int num0 = 10; // 정수형 변수 선언 및 초기화
int& num1 = num0; // num
0에 대한 참조 선언
int* const num2 = &num0; // num0에 대한 상수 포인터 선언
int num3 = 20; // 또 다른 정수형 변수 선언 및 초기화
// 상수 포인터는 참조처럼 초기화 후 가리키는 대상을 변경할 수 없음
// num2 = &num3; // 컴파일 오류 발생
}