반응형
엔진 코드 중에 UniquePtr.h 라는 포인터 처리 코드가 있습니다.
코드에서 포인터를 사용할 경우 해당 헤더파일을 반드시 참조하게 되어 디버그에러시 해당 파일과 잘못연결되어 에러를 뱉는 경우가 허다합니다.
메모리에 올렸다 해제했다를 잘해야 하는데, 그러지 못한 경우 해당 코드에서 문제를 일으키는 것입니다.
포인터의 개념을 잘 숙지하여 해당 코드와 문제가 일으나지 않도록 관리하는 것이 필요합니다.
자, 이제 포인터에 대해서 자세히 알아봅시다..
포인터란 무엇일까?
포인터는 **"다른 변수의 메모리 주소를 가리키는 변수"**라고 생각하면 됩니다. 조금 더 쉽게 말하면, 포인터는 다른 데이터가 저장된 위치를 기억하는 변수예요.
비유로 이해하기
포인터를 주소로, 그리고 변수를 집이라고 생각해볼게요.
- 변수는 데이터가 저장된 "집"이에요.
- 포인터는 그 집이 어디 있는지 알려주는 "주소"입니다.
예를 들어, 집(변수) 안에 사람이 살고 있다고 하면, 포인터는 그 사람이 살고 있는 집의 위치를 알려주는 주소를 기억하고 있는 거예요.
포인터 사용해 보기
기본 변수와 포인터의 차이
- 보통의 변수는 데이터를 직접 저장합니다.
- 포인터는 데이터를 저장하는 것이 아니라, **그 데이터가 어디에 있는지(메모리 주소)**를 저장합니다.
cpp
코드 복사
int number = 10; // 그냥 변수, 10이라는 숫자를 저장함 int* pointer = &number; // 포인터, number의 메모리 주소를 저장함
여기서:
- int number는 숫자 10을 저장하는 일반 변수입니다.
- int* pointer는 number 변수의 메모리 주소를 저장하는 포인터입니다.
- &number는 number의 메모리 주소를 의미해요.
포인터의 기호
- * : 포인터를 선언할 때 사용합니다. 예를 들어, int*는 "정수형을 가리키는 포인터"라는 의미입니다.
- & : 변수의 메모리 주소를 얻기 위해 사용합니다.
- * (역참조) : 포인터가 가리키는 주소에 있는 값을 가져오기 위해 사용합니다.
cpp
코드 복사
#include <iostream> using namespace std; int main() { int number = 10; // 일반 변수 int* pointer = &number; // 포인터 변수, number의 주소를 저장 cout << "number의 값: " << number << endl; // number의 값 출력 (10) cout << "pointer가 가리키는 값: " << *pointer << endl; // 포인터가 가리키는 값 출력 (10) cout << "number의 주소: " << &number << endl; // number의 메모리 주소 출력 cout << "pointer의 값: " << pointer << endl; // pointer에 저장된 주소 출력 (number의 주소와 같음) return 0; }
왜 포인터를 사용할까?
포인터가 중요한 이유는 메모리의 직접적인 접근과 효율적인 데이터 처리를 가능하게 하기 때문이에요.
- 동적 메모리 할당: 프로그램이 실행될 때 필요한 만큼 메모리를 요청하고 사용할 수 있어요.
- 예를 들어, 프로그램이 실행될 때 사용자가 원하는 만큼의 데이터를 저장하려면, 포인터를 사용해 메모리를 동적으로 할당할 수 있습니다.
cpp코드 복사int* p = new int; // 정수형 메모리 공간을 동적으로 할당받고, 그 주소를 p에 저장 *p = 20; // 할당된 메모리 공간에 20을 저장 delete p; // 사용한 메모리를 해제 - 데이터 공유: 함수에서 변수를 복사하지 않고, 원래 데이터를 직접 변경할 수 있어요.
- 예를 들어, 함수에 변수의 포인터를 전달하면 함수 내부에서 그 값을 직접 변경할 수 있습니다.
cpp코드 복사void changeValue(int* p) { *p = 100; // 포인터가 가리키는 변수의 값을 변경 } int main() { int number = 10; changeValue(&number); // number의 주소를 함수에 전달 cout << "number의 값: " << number << endl; // 출력 결과: 100 return 0; } - 배열 처리: 포인터는 배열과 밀접하게 연관되어 있어요. 배열의 첫 번째 요소의 주소를 통해 전체 배열을 처리할 수 있습니다.
-
cpp코드 복사int arr[3] = {1, 2, 3}; int* p = arr; // 배열의 첫 번째 요소의 주소를 저장 cout << *p << endl; // 첫 번째 요소 출력 (1) cout << *(p + 1) << endl; // 두 번째 요소 출력 (2)
주의할 점
- 잘못된 포인터 접근: 초기화되지 않은 포인터를 사용하면 프로그램이 충돌할 수 있습니다. 항상 포인터를 사용할 때는 초기화하고 유효성을 확인하는 것이 중요합니다.
cpp코드 복사int* p = nullptr; // 포인터를 초기화하지 않으면 위험!
- 동적 메모리 해제: 동적으로 할당한 메모리를 해제하지 않으면 메모리 누수가 발생합니다. delete를 사용해 메모리를 꼭 해제해야 합니다.
정리
- 포인터는 메모리 주소를 저장하는 변수입니다.
- *와 & 같은 기호를 사용해 메모리 주소를 얻거나 값을 참조합니다.
- 포인터는 효율적인 데이터 처리와 메모리 관리를 가능하게 해줍니다.
반응형
'자체 개발 > Unreal 빌드 관련' 카테고리의 다른 글
패키지 빌드 성공 후 디버그 방법. (0) | 2024.11.28 |
---|---|
AutogenShaderHeaders.ush 삭제 조심 (0) | 2024.11.25 |
소스코드 빌드 성공 후 각 폴더의 역할을 잘 파악하자. (0) | 2024.11.23 |
패키징시 플러그인 충돌과 GameFeatureData 를 주의하라. (0) | 2024.11.20 |
visual studio 2022 가 잘못 깔렸을 경우 다시 까는 방법 (0) | 2024.11.18 |