[C++] 포인터, 상수, 참조
포인터 (Pointer)
개체의 메모리 주소를 저장하는 변수이다. 힙에 새 개체를 할당할 때, 함수를 다른 함수에 전달할 때, 배열 또는 기타 데이터 구조의 요소를 반복할 때 주로 사용한다.
int *a; //C스타일
int* a; //C++스타일
int a = 3; //a는 3이고 주소값 x를 갖는다.
int* b; //b는 포인터이다.
b = &a; //b는 a의 주소값을 가리킨다. 즉, b는 x이며, *b == a 이다.
*b += 1; //*b == a 와 같기때문에 a += 1 즉, a = 4;
포인터는 형식화된 개체 또는 void를 가리킬 수 있는데, 프로그램이 메모리의 힙에 개체를 할당하면 포인터 형태로 해당 개체의 주소를 받고 이것을 소유 포인터라고 한다. 이 소유 포인터를 더 이상 사용하지 않은 경우 명시적으로 메모리를 해제해 주어야한다. new와 delete를 이용하여 메모리를 할당/해제 가능하다.
int* p1 = new int;
delete p1;
int* p2 = new int[10];
delete[] p2;
new : 어떤 데이터형을 원하는지 new 연산자를 말해주면 그에 알맞은 크기와 메모리 블록을 찾아내고 그 블록의 주소를 리턴한다.
delete : 사용한 메모리를 다시 메모리풀로 환수한다. 환수된 메모리는 프로그램의 다른부분에서 다시 사용 가능하다.
new를 사용했을 때 다 사용하면 delete를 사용하여 메모리 누수 현상을 방지하자!
상수 ( Const)
항상 일정한 값을 가지는 수를 의미하며, 프로그래밍에서는 const 로 표시된 '일부'가 프로그램 실행 중 변경될 수 없음을 의미한다.
포인터와 상수
//Case01
int* pValue01;
//비const 데이터를 가리키는 비const포인터, 자유로운 수정 가능
//Case02
const int* pValue02;
//const 정수를 카리키는 비const포인터, 포인터 수정 가능
//Case03
int* const pValue03;
//정수를 가리키는 const포인터, 포인터 변경 불가능
//Case04
const int* const pValue04;
//const 정수를 가리키는 const 포인터, 포인터와 데이터 둘다 변경 불가능
const의 위치에 따라 수정 가능에 대한 여부가 바뀐다.
함수와 상수
//Const 미사용 예시
class User
{
public:
void SetName(Char* name);
char* GetName();
private:
char m_name[128];
};
//...
void User::SetName(Char* name)
{
::strcpy(m_name, name);
}
char* User::GetName()
{
return m_name;
}
//좋지 않음
성능상의 이유로 포인터가 전달 된 것인지, 데이터를 변경해도 좋은것인지를 구분지을 수 있게 해준다. 함수 개체를 주고 받는데 용이하다.
//Const 사용한 좋은 예시
class User
{
public:
void SetName(const Char* name);
const char* GetName();
private:
char m_name[128];
};
//...
void User::SetName(const Char* name)
{
::strcpy(m_name, name);
}
const char* User::GetName()
{
return m_name;
}
참조 ( Reference )
개체를 의미하는 다른 이름으로 참조에 수행되는 작업은 원본 개체에 직접 영향을 준다. 참조는 포인터와 마찬가지로 메모리의 다른 위치에 있는 개체의 주소를 저장한다.
int a = 1;
int& b = a; // b는 a를 참조
b = 200; //a와b 둘다 200값이 된다.
FRotator rot = actor.GetRotator();
FRotator& invertRot = rot;
invertRot.Inverse(); //rot과 invertRot 값모두 반전값이 된다.
포인터와 참조의 차이점
1. 참조는 .(도트)를 이용하며 포인터는 ->연산자를 이용한다.
2. 참조는 선언된 직후에 바로 초기화를 해야하며 한번만 초기화가 가능하다.
3. 참조는 Null값이 될 수 없다. 그러나 항상 가르키는 것이 유효하다는 의미는 아니다.
4. 참조는 삭제하거나 새로 만들 수 없다.
참조와 함수
참조의 가장 주된 활용 분야는 인자를 전달하는 것, 함수로부터 값을 리턴하는 것이다.
void User::SetRotation(const FRotator& rot)
{
m_rot = rot;
}
const FRotator& User::GetRotation() const
{
return m_rot;
}
//위와 같이 함수를 구성할 경우 복사가 되지 않아 효율이 좋다
참조의 장점
1. 코드가 깔끔하다.
FRotator rot01;
FRotator rot02;
rot01 = *(User->GetRotation()); //포인터
rot02 = User.GetRotation(); //참조
2. 참조는 항상 개체를 가리키기때문에 Null을 가리키는 일이 없다.
3. 참조가 가리키는 개체가 참조를 이용하는 코드에 의해 제거되지 않는다. 포인터의 경우는 제거가 가능하므로 위험하다.
참조가 포인터보다 좋아보이지만 포인터를 사용해야할 경우도 있다. 동적으로 개체를 만들고 제거할 때, 함수가 실패했을 경우 Null값을 알려야할 때, 포인터 연산을 이용할 때는 포인터를 이용하도록 하자!
C++의 포인터 / 상수 / 참조에 대해 알아보았다. 각각을 적절히 활용하여 좋은 퍼포먼스를 낼 수 있도록 해보자!!
'Game Programming > 게임 프로그래밍 C++' 카테고리의 다른 글
[C++] 순차 컨테이너와 벡터 (0) | 2022.09.16 |
---|---|
[C++] STL (0) | 2022.09.16 |
[C++] 메모리 할당 (0) | 2022.09.12 |
[C++] 형변환과 템플릿 (0) | 2022.09.12 |
[C++] 클래스와 상속 (0) | 2022.09.11 |