포인터와 참조
Coddy C++ 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 104개 중 13번째.
이제 스택과 힙 메모리를 이해했으므로, 메모리 위치를 직접 다룰 수 있게 해주는 도구인 포인터와 참조에 대해 알아봅시다.
포인터는 다른 변수의 메모리 주소를 저장합니다. *를 사용하여 선언하고 &를 사용하여 주소를 가져옵니다.
int value = 42;
int* ptr = &value; // ptr은 value의 주소를 저장합니다
std::cout << ptr; // 메모리 주소를 출력합니다
std::cout << *ptr; // 역참조: 42를 출력합니다참조(reference)는 기존 변수의 별칭입니다. 한 번 바인딩되면, 항상 해당 변수를 가리킵니다. &를 사용하여 선언합니다.
int value = 42;
int& ref = value; // ref는 value의 별칭입니다
ref = 100; // value를 100으로 변경합니다
std::cout << value; // 100을 출력합니다주요 차이점:
| 포인터 (Pointers) | 참조 (References) |
|---|---|
| null이 될 수 있음 | 반드시 초기화되어야 함 |
| 재할당 가능 | 재바인딩 불가 |
*를 사용하여 값에 접근 | 값에 직접 접근 |
| 아무것도 가리키지 않을 수 있음 | 항상 유효함 |
둘 다 복사 없이 객체를 함수에 효율적으로 전달하고, 힙 할당 메모리를 다루는 데 필수적입니다. 참조(References)는 더 안전하고 간단한 반면, 포인터(pointers)는 재할당하거나 null 여부를 확인해야 할 때 더 많은 유연성을 제공합니다.
챌린지
쉬움데이터를 수정할 때 포인터와 참조가 어떻게 다르게 작동하는지 보여주는 간단한 값 조작 시스템을 만들어 보겠습니다.
코드를 구성하기 위해 두 개의 파일을 생성합니다:
ValueOps.h: 정수 값을 서로 다른 방식으로 수정하는 세 가지 함수를 정의합니다:doubleByPointer(int* ptr)— 포인터를 받아 그 포인터가 가리키는 값을 두 배로 만듭니다.tripleByReference(int& ref)— 참조를 받아 그 값을 세 배로 만듭니다.swapValues(int* a, int* b)— 두 개의 포인터를 받아 그 포인터들이 가리키는 값을 서로 바꿉니다.
main.cpp: 입력으로부터 두 개의 정수를 읽은 다음, 포인터와 참조를 모두 시연합니다:- 원본 값을 출력합니다:
"Original: <first> <second>" - 첫 번째 값에
doubleByPointer를 사용한 후 출력합니다:"After double: <first>" - 두 번째 값에
tripleByReference를 사용한 후 출력합니다:"After triple: <second>" swapValues를 사용하여 두 값을 바꾼 후 출력합니다:"After swap: <first> <second>"
- 원본 값을 출력합니다:
포인터를 사용하여 함수를 호출할 때는 주소 연산자(&)를 사용하여 변수의 주소를 전달해야 함을 기억하세요. 참조는 더 자연스럽게 작동합니다 — 변수를 직접 전달하면 됩니다.
#include "ValueOps.h"를 사용하여 main.cpp에 헤더 파일을 포함시키세요.
치트 시트
포인터(pointer)는 다른 변수의 메모리 주소를 저장합니다. *를 사용하여 선언하고, &를 사용하여 주소를 가져옵니다:
int value = 42;
int* ptr = &value; // ptr은 value의 주소를 가집니다
std::cout << ptr; // 메모리 주소를 출력합니다
std::cout << *ptr; // 역참조: 42를 출력합니다참조(reference)는 기존 변수의 별칭입니다. &를 사용하여 선언합니다:
int value = 42;
int& ref = value; // ref는 value의 별칭입니다
ref = 100; // value를 100으로 변경합니다
std::cout << value; // 100을 출력합니다주요 차이점:
| 포인터 (Pointers) | 참조 (References) |
|---|---|
| null이 될 수 있음 | 반드시 초기화되어야 함 |
| 재할당 가능 | 재할당(rebound) 불가능 |
*를 사용하여 값에 접근 | 직접 값에 접근 |
| 아무것도 가리키지 않을 수 있음 | 항상 유효함 |
포인터를 사용하여 함수를 호출할 때는 주소 연산자(&)를 사용하여 변수의 주소를 전달합니다. 참조는 직접 작동하므로 변수를 그대로 전달하면 됩니다.
직접 해보기
#include <iostream>
#include "ValueOps.h"
using namespace std;
int main() {
// 입력으로부터 두 개의 정수 읽기
int first, second;
cin >> first;
cin >> second;
// 원본 값 출력
cout << "Original: " << first << " " << second << endl;
// TODO: 첫 번째 값에 doubleByPointer 사용 (&를 사용하여 주소 전달)
// TODO: double 호출 후 출력
// TODO: 두 번째 값에 tripleByReference 사용 (변수를 직접 전달)
// TODO: triple 호출 후 출력
// TODO: swapValues를 사용하여 두 값을 서로 바꿈 (&를 사용하여 주소 전달)
// TODO: swap 호출 후 출력
return 0;
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.