[C++] 포인터 vs 참조, const
포인터 vs 참조
인프런 Rookiss님의 'Part1: C++ 프로그래밍 입문' 강의를 기반으로 정리한 필기입니다.
😎[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강의 들으러 가기!
포인터 vs 참조
성능 : 포인터와 참조 똑같다
편의성 : 참조 승!
1. 편의성 관련
편의성 관련
- 편의성이 좋다는게 꼭 장점만은 아니다.
- 포인터는 주소를 넘기니 확실하게 원본을 넘긴다는 힌트를 줄 수 있는데
- 참조는 자연스럽게 모르고 지나칠 수도 있음!
- ex) 마음대로 고친다면?
- const를 사용해서 이런 마음대로 고치는 부분 개선 가능
void PrintInfoByRef(const StatInfo& info)
{
cout << "-------------------- " << endl;
cout << "HP: " << info.hp << endl;
cout << "ATT: " << info.attack << endl;
cout << "DEF: " << info.defence << endl;
cout << "-------------------- " << endl;
}
// 신입이 왔다
// info.hp = 10000; 실수로 다음과 같이 기입해도 에러가 뜬다.
- 참고로 포인터도 const를 사용 가능
* 기준으로 앞에 붙이느냐, 뒤에 붙이느냐에 따라 의미가 달라진다.
- const 별 뒤에 붙인다면?
- StatInfo* const info
- info라는 바구니의 내용물(주소)을 바꿀 수 없음
- info는 주소값을 갖는 바구니 -> 이 주소값이 고정이다!
- 데이터는 바꿀 수 있고 주솟값은 바꿀 수 없다.
- info[주소값] 주소값[데이터]
- info = &globalInfo; (O)
- info->hp = 10000; (X)
- const 별 이전에 붙인다면?
- const StatInfo* info
- StatInfo const* info
- 위의 두가지 표현은 같은 의미다.
- info가 '가리키고 있는' 바구니의 내용물을 바꿀 수 없음
- '원격' 바구니의 내용물을 바꿀 수 없음.
- 주소값은 바꿀 수 있고 데이터는 바꿀 수 없다.
- info[주소값] 주소값[데이터]
- info = &globalInfo; (O)
- info->hp = 10000; (X)
info[주소값] 주소값[데이터]
const 별 뒤에 붙인다면? | const 별 이전에 붙인다면? | |
|
|
둘 다 막는 경우
const StatInfo* const info는 둘 다 바꿀 수 없다.
// [매개변수][RET][지역변수(info)] [매개변수(&info)][RET][지역변수]
void PrintInfoByPtr(const StatInfo* const info)
{
if (info == nullptr)
return;
cout << "-------------------- " << endl;
cout << "HP: " << info->hp << endl;
cout << "ATT: " << info->attack << endl;
cout << "DEF: " << info->defence << endl;
cout << "-------------------- " << endl;
}
2. 초기화 여부
초기화 여부
- 참조 타입은 바구니의 2번째 이름 (별칭?)
- 참조하는 대상이 없으면 안됨
- 참조 타입은 이런 nullptr과 같은 개념이 없다. 공허한 값을 가리킬 수 없다.
- 반면 포인터는 그냥 어떤~ 주소라는 의미
- 대상이 실존하지 않을 수도 있음
- 포인터에서 '없다'는 의미로?
- nullptr
- 공허한 값을 가리킨다.
- nullptr인 상황에서 해당 주소에 접근하려하면 크러쉬가 난다.
- nullptr
StatInfo* pointer = nullptr;
pointer = &info;
PrintInfoByPtr(pointer);
/* StatInfo& reference; 참조하는 대상이 없다. 불가능한 표기
reference = info; */
StatInfo& reference = info; // 참조 타입은 다음과 같이 표기. 위와 같이 표기가 불가능하다.
PrintInfoByRef(reference);
그래서 참조와 포인터 중 어떤걸 사용하는게 좋은가?
- 사실 Team By Team... 정해진 답은 없다.
- ex) 구글에서 만든 오픈소스를 보면 거의 무조건 포인터 사용
- ex) 언리얼 엔진에선 reference도 애용
- 없는 경우도 고려해야 한다면 pointer (null 체크 필수)
- 바뀌지 않고 읽는 용도(read only)만 사용하면 const ref&
- 그 외 일반적으로 reference (명시적으로 호출할 때 OUT을 붙인다)
- 단, 다른 사람이 pointer로 만들어 놓은걸 이어서 만든다면, 계속 pointer (섞어 사용하지 않는다)
#include <iostream>
using namespace std;
//...
StatInfo globalInfo;
// [매개변수][RET][지역변수(info)] [매개변수(&info)][RET][지역변수]
void PrintInfoByPtr(const StatInfo* const info)
{
if (info == nullptr)
return;
cout << "HP: " << info->hp << endl;
cout << "ATT: " << info->attack << endl;
cout << "DEF: " << info->defence << endl;
}
void PrintInfoByRef(const StatInfo& info)
{
cout << "HP: " << info.hp << endl;
cout << "ATT: " << info.attack << endl;
cout << "DEF: " << info.defence << endl;
}
#define OUT
void ChangeInfo(OUT StatInfo& info)
{
info.hp = 1000;
}
int main()
{
StatInfo* pointer = nullptr;
pointer = &info;
PrintInfoByPtr(pointer);
StatInfo& reference = info; // 참조 타입은 다음과 같이 표기. 위와 같이 표기가 불가능하다.
PrintInfoByRef(reference);
ChangeInfo(OUT info);
// 보너스) 포인터로 사용하던걸 참조로 넘겨주려면?
// pointer[ 주소(&info) ] info[ 데이터 ]
PrintInfoByRef(*pointer);
// 위의 것을 풀어쓰면 아래와 같다.
// StatInfo& ref = *pointer;
// PrintInfoByRef(ref)
// 보너스) 참조로 사용하던걸 포인터로 넘겨주려면?
// pointer[ 주소 ] reference, info[ 데이터 ]
PrintInfoByPtr(&reference);
// 위의 것을 풀어쓰면 아래와 같다.
// StatInfo* ptr = &reference;
// PrintInfoByPtr(ptr)
return 0;
}
코드
더보기
#include <iostream>
using namespace std;
struct StatInfo
{
int hp; // +0
int attack; // +4
int defence; // +8
};
// [매개변수][RET][지역변수(info)] [매개변수(&info)][RET][지역변수]
void CreateMonster(StatInfo* info)
{
info->hp = 100;
info->attack = 8;
info->defence = 5;
}
// 특정 조건을 만족하는 몬스터를 찾는 함수
StatInfo* FindMonster()
{
// TODO : Heap 영역에서 뭔가를 찾아봄
// 찾았다!
// return monster~;
return nullptr; // 못 찾았다
}
StatInfo globalInfo;
// [매개변수][RET][지역변수(info)] [매개변수(&info)][RET][지역변수]
void PrintInfoByPtr(const StatInfo* const info)
{
if (info == nullptr)
return;
cout << "-------------------- " << endl;
cout << "HP: " << info->hp << endl;
cout << "ATT: " << info->attack << endl;
cout << "DEF: " << info->defence << endl;
cout << "-------------------- " << endl;
// const 별 뒤에 붙인다면?
// StatInfo* const info
// info라는 바구니의 내용물(주소)을 바꿀 수 없음
// info는 주소값을 갖는 바구니 -> 이 주소값이 고정이다!
// const 별 이전에 붙인다면?
// const StatInfo* info
// info가 '가리키고 있는' 바구니의 내용물을 바꿀 수 없음
// '원격' 바구니의 내용물을 바꿀 수 없음
// info[주소값] 주소값[데이터]
// info = &globalInfo;
// info->hp = 10000;
// const StatInfo* const info는 둘 다 바꿀 수 없다.
}
void PrintInfoByRef(const StatInfo& info)
{
cout << "-------------------- " << endl;
cout << "HP: " << info.hp << endl;
cout << "ATT: " << info.attack << endl;
cout << "DEF: " << info.defence << endl;
cout << "-------------------- " << endl;
}
// 신입이 왔다
// info.hp = 10000; 실수로 다음과 같이 기입해도 에러가 뜬다.
#define OUT
void ChangeInfo(OUT StatInfo& info)
{
info.hp = 1000;
}
int main()
{
StatInfo info;
CreateMonster(&info);
// 포인터 vs 참조 세기의 대결
// 성능 : 똑같음!
// 편의성 : 잠조 승!
// 1) 편의성 관련
// 편의성이 좋다는게 꼭 장점만은 아니다.
// 포인터는 주소를 넘기니 확실하게 원본을 넘긴다는 힌트를 줄 수 있는데
// 참조는 자연스럽게 모르고 지나칠 수도 있음!
// ex) 마음대로 고친다면?
// const를 사용해서 이런 마음대로 고치는 부분 개선 가능
// 참고로 포인터도 const를 사용 가능
// * 기준으로 앞에 붙이느냐, 뒤에 붙이느냐에 따라 의미가 달라진다.
// 2) 초기화 여부
// 참조 타입은 바구니의 2번째 이름 (별칭?)
// -> 참조하는 대상이 없으면 안됨
// 반면 포인터는 그냥 어떤~ 주소라는 의미
// -> 대상이 실존하지 않을 수도 있음
// 포인터에서 '없다'는 의미로? nullptr
// 참조 타입은 이런 nullptr
StatInfo* pointer = nullptr;
pointer = &info;
PrintInfoByPtr(pointer);
/* StatInfo& reference; 참조하는 대상이 없다. 불가능한 표기
reference = info; */
StatInfo& reference = info; // 참조 타입은 다음과 같이 표기. 위와 같이 표기가 불가능하다.
PrintInfoByRef(reference);
// 그래서 결론은?
// 사실 Team By Team... 정해진 답은 없다
// ex) 구글에서 만든 오픈소스를 보면 거의 무조건 포인터 사용
// ex) 언리얼 엔진에선 reference도 애용
// 없는 경우도 고려해야 한다면 pointer (null 체크 필수)
// 바뀌지 않고 읽는 용도(read only)만 사용하면 const ref&
// 그 외 일반적으로 ref (명시적으로 호출할 때 OUT을 붙인다)
// 단, 다른 사람이 pointer로 만들어 놓은걸 이어서 만든다면, 계속 pointer (섞어 사용하지 않는다)
ChangeInfo(OUT info);
// 보너스) 포인터로 사용하던걸 참조로 넘겨주려면?
// pointer[ 주소(&info) ] info[ 데이터 ]
PrintInfoByRef(*pointer); // 다른식의 표기 : StatInfo& ref = *pointer;
// 보너스) 참조로 사용하던걸 포인터로 넘겨주려면?
// pointer[ 주소 ] reference, info[ 데이터 ]
PrintInfoByPtr(&reference); // 다른식의 표기 : StatInfo* ptr = &reference;
return 0;
}
'⭐ Programming > C++' 카테고리의 다른 글
[C++] 포인터 vs 배열 (0) | 2022.03.26 |
---|---|
[C++] 배열 기초 (0) | 2022.03.26 |
[C++] 참조 기초 (0) | 2022.03.26 |
[C++] 포인터 실습 (0) | 2022.03.26 |
[C++] 포인터 연산 (0) | 2022.03.25 |
댓글
이 글 공유하기
다른 글
-
[C++] 포인터 vs 배열
[C++] 포인터 vs 배열
2022.03.26 -
[C++] 배열 기초
[C++] 배열 기초
2022.03.26 -
[C++] 참조 기초
[C++] 참조 기초
2022.03.26 -
[C++] 포인터 실습
[C++] 포인터 실습
2022.03.26