🙇‍♀️참조 기초 복습


🪐이전까지의 방식들

struct StatInfo // 연습용 구조체
{
	int hp;
	int attack;
	int defence;
};
void CreateMonster(StatInfo* monster) // 포인터 방식
{
	monster->hp = 40;
	monster->attack = 8;
	monster->defence = 1;
}

void CreateMonster(StatInfo monster) // 복사 방식
{
	monster.hp = 40;
	monster.attack = 8;
	monster.defence = 1;
}


🪐값 전달 방식

void PrintInfoByCoppy(StatInfo info)
{
	cout << "HP: " << info.hp << endl;
}

PrintInfoByCoppy(monster); // 사용법

값이 복사 되는 방식이며 구조체의 크기가 매우 크다면 구조체 크기만큼 복사 되기 떄문에 부담스럽다.

값을 바꾸는 것이 아니라 읽기만 한다면 사용가능하다.


🪐주소 전달 방식

void PrintInfoByPtr(StatInfo* info)
{
	cout << "HP: " << info->hp << endl;
}

PrintInfoByPtr(&monster); // 사용법

포인터를 통한 주소를 전달하는 방식이며 주소 크기인 8바이트만 사용한다는 점이 장점이다.

구조체 안 변수를 확인할 때 -> 연산자를 사용해야 한다는 것이 특징이다.


🪐참조 전달 방식

void PrintInfoByRef(StatInfo& info)
{
	cout << "HP: " << info.hp << endl;
}

PrintInfoByRef(monster); // 사용법

참조 전달 방식은 & 연산자를 사용하는 것이 특징이고 사용할 때 .을 사용한다.

로우레벨(어셈블리) 관점에서 실제 작동 방식은 int*와 똑같다.

C++ 관점에서는 number라는 바구니에 또 다른 이름을 부여한 것이다. (별칭의 개념)

int number = 1;

int& reference = number;
reference = 2;

여기서 reference를 바꾼다면 진퉁인 number를 바꾸는 것과 같다


🙇‍♀️포인터 vs 참조 복습


🪐포인터 vs 참조

성능적으로는 완전히 동일하다. 편의성은 참조가 더욱 편리하지만 함수를 사용시 &을 사용하지 않기 때문에 원본 데이터를 훼손 시킬 우려가 존재한다.

void PrintInfoByRef(const StatInfo& info)
{
	cout << "HP: " << info.hp << endl;

  // info.hp = 10; // Error
}

PrintInfoByRef(monster); // 사용법

원본 데이터를 지키기 위해 const를 사용하면 된다. 참조의 경우 대부분 저렇게 사용하는게 컨벤션!

#define OUT

void ChangeInfo(OUT StatInfo& info)
{
  info.hp = 1000;
}

ChangeInfo(OUT info); // 사용법

문법적으로만 볼 떄 참조는 복사 형식과 똑같기 때문에 명시적으로 OUT이라는 아무런 역할이 없는 것을 붙여서 원본을 사용한다는 것을 표시한다.


🪐포인터와 const

포인터에서 const는 * 앞과 뒤로 구분한다.

  • 별 뒤에 붙인다면?
    • StatInfo* const info
    • info라는 바구니의 내용물(주소)을 바꿀 수 없다
    • info는 주소값을 갖는 바구니 -> 이 주소값이 고정이다!
    • 아래 예시에서 info = &globalInfo;가 안된다
  • 별 이전에 붙인다면?
    • const StatInfo* info
    • info가 ‘가리키고 있는’ 바구니의 내용물을 바꿀 수 없다
    • ‘원격’ 바구니의 내용물(주소값의 데이터)을 바꿀 수 없다
    • 아래 예시에서 info->hp = 10000;가 안된다
StatInfo globalInfo; // 구조체 전역변수

void PrintInfoByPtr(StatInfo* info) // (const StatInfo* info) or (StatInfo* const info) or (const StatInfo* const info)
{
	cout << "HP: " << info->hp << endl;
}

info = &globalInfo;

info->hp = 10000;


🪐초기화 여부

참조 타입은 바구니의 2번째 이름으로 참조하는 대상이 없으면 안된다.

포인터는 대상이 없어도 된다. -> 대상이 실존하지 않을 수도 있다

  • 포인터에서 ‘없다’는 의미는 어떻게 표현?
    • nullptr
    • StatInfo* pointer = nullptr;처럼 사용
    • int a = nullptr는 에러가 발생

참조 타입은 이런 nullptr의 개념이 없다

StatInfo* pointer; // StatInfo구조체 포인터 변수
pointer = &info; // 포인터 변수에 info라는 StatInfo형 구조체 변수 주소를 넣음
// StatInfo* pointer = &info; 와 같다
PrintInfo(pointer); // PrintInfo(&info);와 같다

// StatInfo& referece; // Error! 참조는 초기화 값이 필요하다
StatInfo& reference = info;
// reference++; // Error 사칙연산 불가!
PrintInfo(reference);


🪐포인터->참조, 참조->포인터

  • 포인터로 사용하던걸 참조로 넘겨주려면?
    • pointer [ 주소(&info) ] ref, info [ 데이터 ] ```cpp StatInfo* pointer = &info;

StatInfo& ref = pointer; PrintInfoByRef(pointer); // PrintInfoByRef(ref);과 같음


* 참조로 사용하던걸 포인터로 넘겨주려면?
  - pointer [ 주소 ]  reference, info [ 데이터 ]
```cpp
StatInfo* ptr = &reference;
PrintInfoByPtr(&reference); // PrintInfoByPtr(ptr);과 같음

태그:

카테고리:

업데이트: