[C++] 포인터
C++ 포인터 정리
1. 기본 포인터 (Raw Pointer)
일반적인 포인터로, 변수의 메모리 주소를 저장하고 가리킬 수 있다.
1
2
3
int x = 10;
int* ptr = &x; // x의 주소 저장
std::cout << *ptr; // 출력: 10 (역참조)
*ptr을 사용하여 포인터가 가리키는 값을 가져올 수 있음.nullptr또는NULL로 초기화하여 쓰레기 값 방지.
1
int* ptr = nullptr; // 안전한 초기화
2. 상수 포인터 (Pointer to Constant)
포인터가 가리키는 값 자체를 변경할 수 없도록 제한하는 포인터.
1
2
3
4
const int x = 10;
const int* ptr = &x; // 상수 포인터 (const int*)
*ptr = 20; // ❌ 오류! 값을 변경할 수 없음
ptr = &y; // ✅ 다른 주소는 가리킬 수 있음
3. 포인터 상수 (Constant Pointer)
포인터가 항상 동일한 메모리 주소만 가리키도록 제한하는 포인터.
1
2
3
4
5
int x = 10;
int y = 20;
int* const ptr = &x; // 포인터 자체가 상수
ptr = &y; // ❌ 오류! 다른 주소로 변경 불가
*ptr = 30; // ✅ 값 변경은 가능
4. 상수 포인터 상수 (Constant Pointer to Constant)
포인터가 가리키는 값과 주소 모두 변경 불가능한 포인터.
1
2
3
4
const int x = 10;
const int* const ptr = &x;
*ptr = 20; // ❌ 오류! 값 변경 불가
ptr = &y; // ❌ 오류! 주소 변경 불가
5. void* 포인터 (Generic Pointer)
특정한 데이터 타입을 지정하지 않은 포인터.
1
2
3
int x = 10;
void* ptr = &x;
std::cout << *(static_cast<int*>(ptr)); // 출력: 10
6. 함수 포인터 (Function Pointer)
함수를 가리키는 포인터로, 동적으로 함수 호출 가능.
1
2
3
4
5
void hello() { std::cout << "Hello, world!"; }
int add(int a, int b) { return a + b; }
void (*funcPtr)() = hello;
funcPtr(); // 실행: Hello, world!
7. 배열 포인터 (Pointer to Array)
배열 전체를 가리키는 포인터.
1
2
3
int arr[3] = {1, 2, 3};
int (*ptr)[3] = &arr;
std::cout << (*ptr)[1]; // 출력: 2
8. this 포인터 (클래스 내부 포인터)
클래스 내부에서 객체 자기 자신을 가리키는 포인터.
1
2
3
4
class Test {
public:
void show() { std::cout << "This address: " << this << std::endl; }
};
9. 스마트 포인터 (Smart Pointer)
C++11부터 제공되는 메모리 자동 관리 포인터.
unique_ptr (소유권 단독)
1
2
#include <memory>
std::unique_ptr<int> ptr = std::make_unique<int>(10);
shared_ptr (참조 카운트)
1
2
3
#include <memory>
std::shared_ptr<int> ptr1 = std::make_shared<int>(10);
std::shared_ptr<int> ptr2 = ptr1; // 참조 카운트 증가
weak_ptr (순환 참조 방지)
1
2
#include <memory>
std::weak_ptr<int> weakPtr;
10. 널 포인터 (Null Pointer)
1
int* ptr = nullptr; // 안전한 초기화
11. 메모리 주소 계산용 포인터 (Pointer Arithmetic)
1
2
3
int arr[] = {10, 20, 30};
int* ptr = arr;
std::cout << *(ptr + 1); // 출력: 20
12. 📌 포인터 종류 정리
| 포인터 종류 | 설명 |
|---|---|
| 기본 포인터 | 일반적인 포인터 |
| 상수 포인터 | 가리키는 값 변경 불가 |
| 포인터 상수 | 포인터 주소 변경 불가 |
| 완전 상수 포인터 | 값 + 주소 변경 불가 |
| void* 포인터 | 타입이 없는 포인터 |
| 함수 포인터 | 함수를 가리키는 포인터 |
| 배열 포인터 | 배열을 가리키는 포인터 |
| this 포인터 | 클래스 내에서 자기 자신 참조 |
| 스마트 포인터 | 메모리 자동 관리 포인터 |
| 널 포인터 | 어떤 객체도 가리키지 않는 포인터 |
| 메모리 주소 계산 포인터 | 포인터 연산 사용 |
번외.
1. int* x; or int *x;
포인터 기호 ‘*‘는 자료형에 붙일까 이름에 붙일까?
정해진 답은 없고 실제도 두 가지 스타일 모두 볼 수있다. 구글 C++ 스타일 가이드에는 두 가지 스타일 모두 사용 가능 하지만, 한 파일에서 한 가지 스타일을 유지 해야 한다고 정한다.
다만, int * x이런 식으로 공백을 둘 다 주는 경우는 잘 없고 구글 스타일 가이드에서도 권장하지 않는다.
You should do this consistently within a single file. When modifying an existing file, use the style in that file.
…
char * c; // Bad - spaces on both sides of *
참고로 char *x 형식이 전통적인 C스타일 이고 변수를 여러개 선언할때 더 직관적이다.
1
2
3
char* a, b; // a, b 둘다 char* 처럼 보이지만 a는 char*, b는 char다.
char *a, b; // 이런 경우는 변수명에 기호를 붙이는 것이 더 직관적일 수 있다.
하지만 두 가지 모두 혼란을 야기하기 때문에 구글 가이드에서는 한 번에 변수를 여러개 선언할때 포인터나 참조 기호가 들어가는 것을 금지 한다.
1
2
3
4
5
6
7
8
9
10
// Fine if helpful for readability.
int x, y;
int x, *y; // Disallowed - no & or * in multiple declaration
int* x, *y; // Disallowed - no & or * in multiple declaration; inconsistent spacing
// 최소한 이런식으로 사용하자.
int x; int *y;
int* x, int y;
결론적으로 일관성을 유지한다면 int* x; or int *x; 둘 다 괜찬다. 포인터 변수 선언은 개별로 하자.