참조 기초

 

인프런 Rookiss님의 'Part1: C++ 프로그래밍 입문' 강의를 기반으로 정리한 필기입니다. 
😎[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문 강의 들으러 가기!

 

 


 

전달 방식들

 

1. 값 전달 방식

-  임시적으로 매개변수에 복사받은 구조체에 접근해서 꺼내쓰는 방식

-  원본 정보는 건드리지 않는다.

-  아래의 경우, 원본의 정보는 건드리지 않고 임시값만 수정하고 함수가 호출되었을때 스택영역은 더 이상 유효하지 않아 날라가기 때문에 아무런 변화도 일어나지 않는다. 

 

[매개변수][RET][지역변수(info)] [매개변수(info(100, 8, 5)][RET][지역변수]
[매개변수][RET][지역변수(info)]

void CreateMonster(StatInfo info)
{
    info.hp = 100;
    info.attack = 8;
    info.defence = 5;
}


[매개변수][RET][지역변수(info)] [매개변수(info)][RET][지역변수]

void PrintInfoByCopy(StatInfo info)
{
    cout << "HP: " << info.hp << endl;
    cout << "ATT: " << info.attack << endl;
    cout << "DEF: " << info.defence << endl;
}

 

 

 

2. 주소 전달 방식

원본(지역변수)에 접근해서 꺼내쓰는 방식

 

[매개변수][RET][지역변수(info)] [매개변수(&info)][RET][지역변수]

void CreateMonster(StatInfo* info)
{
    info->hp = 100;
    info->attack = 8;
    info->defence = 5;
}

 

[매개변수][RET][지역변수(info)] [매개변수(&info)][RET][지역변수]

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

 

 

 

3.  참조 전달 방식

-  값 전달처럼 편리하게 사용하고!
-  주소 전달처럼 주소값을 이용해 진퉁을 건드리는 일석이조의 방식!

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

 

 


 

 

 


 StatInfo 구조체가 1000바이트 짜리 대형 구조체라면?

-  (값 전달) StatInfo로 넘기면 1000바이트가 복사됨

-  (주소 전달) StatInfo*는 8바이트

-  (참조 전달) StatInf&*는 8바이트


 

4바이트 정수형 바구니를 사용할거야. 앞으로 그 바구니 이름을 number라고 할게.

그러니까 number에서 뭘 꺼내거나, number에 뭘 넣는다고 하면 찰떡같이 알아듣고 해당 주소(dat, stack, heap)에 1을 넣어주면 된다!


int number = 1;

   

* 주소를 담는 바구니

int 그 바구니를 따라가면 int 데이터(바구니)가 있음

 

int* pointer = &number;

pointer 바구니에 있는 주소를 타고 이동해서, 그 멀리  있는 바구니에 2를 넣는다

*pointer = 2;

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

실제로 실행해보면 포인터랑 100% 똑같다.

int& reference = number;

C++ 관점에서는 number라는 바구니에 또 다른 이름을 부여한 것

number라는 바구니에 reference라는 다른 이름을 지어줄게~
앞으로 reference 바구니에다가 뭘 꺼내거나 넣으면,

실제 number 바구니(진짜에다가) 그 값을 꺼내거나 넣으면 됨!

reference = 3;

 

그런데 귀찮게 또 다른 이름을 짓는 이유는?

- 그냥 number = 3이라고 해도 똑같지만 참조 전달 때문!

 

int main()
{
    StatInfo info;
    CreateMonster(&info);

    PrintInfoByCopy(info);
    PrintInfoByPtr(&info);
    PrintInfoByRef(info);

    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;
}

// [매개변수][RET][지역변수(info)] [매개변수(info(100, 8, 5)][RET][지역변수]
// [매개변수][RET][지역변수(info)]
void CreateMonster(StatInfo info)
{
    info.hp = 100;
    info.attack = 8;
    info.defence = 5;
}

//값을 수정하지 않는다면, 양쪽 다 일단 문제 없음

// 1) 값 전달 방식
// 임시적으로 매개변수에 복사받은 구조체에 접근해서 꺼내쓰는 방식
// [매개변수][RET][지역변수(info)] [매개변수(info         )][RET][지역변수]
void PrintInfoByCopy(StatInfo info)
{
    cout << "-------------------- " << endl;
    cout << "HP: " << info.hp << endl;
    cout << "ATT: " << info.attack << endl;
    cout << "DEF: " << info.defence << endl;
    cout << "-------------------- " << endl;
}

// 2) 주소 전달 방식
// 원본(지역변수)에 접근해서 꺼내쓰는 방식
// [매개변수][RET][지역변수(info)] [매개변수(&info)][RET][지역변수]
void PrintInfoByPtr(StatInfo* info)
{
    cout << "-------------------- " << endl;
    cout << "HP: " << info->hp << endl;
    cout << "ATT: " << info->attack << endl;
    cout << "DEF: " << info->defence << endl;
    cout << "-------------------- " << endl;
}

// 3) 참조 전달 방식
// 값 전달처럼 편리하게 사용하고!
// 주소 전달처럼 주소값을 이용해 진퉁을 건드리는
// 일석이조의 방식!
void PrintInfoByRef(StatInfo& info)
{
    cout << "-------------------- " << endl;
    cout << "HP: " << info.hp << endl;
    cout << "ATT: " << info.attack << endl;
    cout << "DEF: " << info.defence << endl;
    cout << "-------------------- " << endl;
}

// StatInfo 구조체가 1000바이트 짜리 대형 구조체라면?
// - (값 전달) StatInfo로 넘기면 1000바이트가 복사됨
// - (주소 전달) StatInfo*는 8바이트
// - (참조 전달) StatInf&*는 8바이트


int main()
{
    // 4바이트 정수형 바구니를 사용할거야
    // 앞으로 그 바구니 이름을 number라고 할게
    // 그러니까 number에서 뭘 꺼내거나, number에 뭘 넣는다고 하면
    // 찰떡같이 알아듣고 해당 주소(dat, stack, heap)에 1을 넣어주면 된다!
    int number = 1;

    // * 주소를 담는 바구니
    // int 그 바구니를 따라가면 int 데이터(바구니)가 있음
    int* pointer = &number;
    // pointer 바구니에 있는 주소를 타고 이동해서, 그 멀리  있는 바구니에 2를 넣는다
    *pointer = 2;

    // 로우레벨(어셈블리) 관점에서 실제 작동 방식은 int*와 똑같음
    // 실제로 실행해보면 포인터랑 100% 똑같다
    int& reference = number;

    // C++ 관점에서는 number라는 바구니에 또 다른 이름을 부여한 것
    // number라는 바구니에 reference라는 다른 이름을 지어줄게~
    // 앞으로 reference 바구니에다가 뭘 꺼내거나 넣으면,
    // 실제 number 바구니(진짜에다가) 그 값을 꺼내거나 넣으면 됨!
    reference = 3;

    // 그런데 귀찮게 또 다른 이름을 짓는 이유는?
    // 그냥 number = 3이라고 해도 똑같지만
    // 참조 전달 때문!

    StatInfo info;
    CreateMonster(&info);

    PrintInfoByCopy(info);
    PrintInfoByPtr(&info);
    PrintInfoByRef(info);

    return 0;
}

 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#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;
}
 
// [매개변수][RET][지역변수(info)] [매개변수(info(100, 8, 5)][RET][지역변수]
// [매개변수][RET][지역변수(info)]
void CreateMonster(StatInfo info)
{
    info.hp = 100;
    info.attack = 8;
    info.defence = 5;
}
 
//값을 수정하지 않는다면, 양쪽 다 일단 문제 없음
 
// 1) 값 전달 방식
// 임시적으로 매개변수에 복사받은 구조체에 접근해서 꺼내쓰는 방식
// [매개변수][RET][지역변수(info)] [매개변수(info         )][RET][지역변수]
void PrintInfoByCopy(StatInfo info)
{
    cout << "-------------------- " << endl;
    cout << "HP: " << info.hp << endl;
    cout << "ATT: " << info.attack << endl;
    cout << "DEF: " << info.defence << endl;
    cout << "-------------------- " << endl;
}
 
// 2) 주소 전달 방식
// 원본(지역변수)에 접근해서 꺼내쓰는 방식
// [매개변수][RET][지역변수(info)] [매개변수(&info)][RET][지역변수]
void PrintInfoByPtr(StatInfo* info)
{
    cout << "-------------------- " << endl;
    cout << "HP: " << info->hp << endl;
    cout << "ATT: " << info->attack << endl;
    cout << "DEF: " << info->defence << endl;
    cout << "-------------------- " << endl;
}
 
// 3) 참조 전달 방식
// 값 전달처럼 편리하게 사용하고!
// 주소 전달처럼 주소값을 이용해 진퉁을 건드리는
// 일석이조의 방식!
void PrintInfoByRef(StatInfo& info)
{
    cout << "-------------------- " << endl;
    cout << "HP: " << info.hp << endl;
    cout << "ATT: " << info.attack << endl;
    cout << "DEF: " << info.defence << endl;
    cout << "-------------------- " << endl;
}
 
// StatInfo 구조체가 1000바이트 짜리 대형 구조체라면?
// - (값 전달) StatInfo로 넘기면 1000바이트가 복사됨
// - (주소 전달) StatInfo*는 8바이트
// - (참조 전달) StatInf&*는 8바이트
 
 
int main()
{
    // 4바이트 정수형 바구니를 사용할거야
    // 앞으로 그 바구니 이름을 number라고 할게
    // 그러니까 number에서 뭘 꺼내거나, number에 뭘 넣는다고 하면
    // 찰떡같이 알아듣고 해당 주소(dat, stack, heap)에 1을 넣어주면 된다!
    int number = 1;
 
    // * 주소를 담는 바구니
    // int 그 바구니를 따라가면 int 데이터(바구니)가 있음
    int* pointer = &number;
    // pointer 바구니에 있는 주소를 타고 이동해서, 그 멀리  있는 바구니에 2를 넣는다
    *pointer = 2;
 
    // 로우레벨(어셈블리) 관점에서 실제 작동 방식은 int*와 똑같음
    // 실제로 실행해보면 포인터랑 100% 똑같다
    int& reference = number;
 
    // C++ 관점에서는 number라는 바구니에 또 다른 이름을 부여한 것
    // number라는 바구니에 reference라는 다른 이름을 지어줄게~
    // 앞으로 reference 바구니에다가 뭘 꺼내거나 넣으면,
    // 실제 number 바구니(진짜에다가) 그 값을 꺼내거나 넣으면 됨!
    reference = 3;
 
    // 그런데 귀찮게 또 다른 이름을 짓는 이유는?
    // 그냥 number = 3이라고 해도 똑같지만
    // 참조 전달 때문!
 
    StatInfo info;
    CreateMonster(&info);
 
    PrintInfoByCopy(info);
    PrintInfoByPtr(&info);
    PrintInfoByRef(info);
 
    return 0;
}
 
cs

'값 전달' 방식 보다는 '주소 전달' 또는 '참조 전달' 방식 위주로 사용하자.

 

 

 

 

pointer 사용방식이랑 reference 사용방식이랑 동일하다.

'⭐ Programming > C++' 카테고리의 다른 글

[C++] 배열 기초  (0) 2022.03.26
[C++] 포인터 vs 참조, const  (0) 2022.03.26
[C++] 포인터 실습  (0) 2022.03.26
[C++] 포인터 연산  (0) 2022.03.25
[C++] 포인터 #2  (0) 2022.03.25