[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
댓글을 사용할 수 없습니다.