๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
C++ ๊ธฐ์ดˆ

[C++] 14. ์ฐธ์กฐ์ž(Reference)

by ์„œ์•„๋ž‘๐Ÿ˜ 2023. 6. 2.

 

 

 

 

โœ… ์ฐธ์กฐ์ž(Reference)

์ฐธ์กฐ์ž๋Š” ํฌ์ธํ„ฐ์™€ ์ƒ๋‹นํžˆ ์œ ์‚ฌํ•œ ๊ฐœ๋…์ด๋‹ค. C์—์„œ๋Š” ํฌ์ธํ„ฐ๋งŒ ์žˆ์—ˆ์ง€๋งŒ C++์—์„œ๋Š” ์ฐธ์กฐ์ž(Reference)๋ผ๋Š” ๊ฐœ๋…์ด ๋„์ž…๋˜๋ฉด์„œ ์ข€ ๋” ํŽธํ•˜๊ฒŒ ์ฃผ์†Œ๊ฐ’์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค. ์‚ฌ์‹ค C++์—์„œ๋„ ํฌ์ธํ„ฐ์— ์˜์กดํ•˜๊ณ  ์‹ถ์ง€ ์•Š์•˜๊ณ  *๊ณผ ->๋ฅผ ์ค„์ด๊ณ  ์‹ถ์—ˆ๋‹ค๊ณ  ํ•œ๋‹ค.

 

์šฐ๋ฆฌ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ํ• ๋‹นํ•˜๊ณ  ๋ณ€์ˆ˜๋ผ๋Š” ๊ฒƒ์œผ๋กœ ์ด๋ฆ„์„ ์ง€์–ด์ค€๋‹ค. ์ฐธ์กฐ์ž๋Š” ์ด ์ด๋ฆ„์— ๋ณ„๋ช…์„ ๋ถ™์—ฌ์ฃผ๋Š” ๊ฒƒ์ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด '๊ทผํ˜ธ'์˜ ๋ณ„๋ช…์ด '๊ทผ๋˜๋ฆฌ'๋ผ๊ณ  ํ–ˆ์„ ๋•Œ '๊ทผํ˜ธ'์—๊ฒŒ ๊ณผ์ž๋ฅผ ์ฃผ๋Š” ๊ฒƒ๊ณผ '๊ทผ๋˜๋ฆฌ'์—๊ฒŒ ๊ณผ์ž๋ฅผ ์ฃผ๋Š” ๊ฒƒ์€ ๋™์ผํ•˜๋‹ค.

 

๊ฒฐ๊ตญ, ์ฐธ์กฐ์ž๋Š” ๋˜ ๋‹ค๋ฅธ ์ด๋ฆ„์„ ๋ถ€์—ฌํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

#include <iostream>

using namespace std;

int main()
{
    int var = 10;
    int &ref = var;

    cout << var << endl;
    cout << ref << endl;

    cout << &var << endl;
    cout << &ref << endl;

    ref = 20;

    cout << var << endl;
    cout << ref << endl;
}

// ์‹คํ–‰๊ฒฐ๊ณผ
// 10
// 10
// 0004D7F3
// 0004D7F3
// 20
// 20

 

์ฝ”๋“œ์—์„œ ์ฐธ์กฐ์ž์™€ var๋Š” ๊ฒฐ๊ตญ ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ๊ณต๊ฐ„์„ ๋ฐ”๋ผ๋ณด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ’๊ณผ ์ฃผ์†Œ ๊ฐ’ ๋ชจ๋‘ ๊ฐ™๋‹ค.

 

 

โœ… Call by Pointer vs Call by Reference

#include <iostream>

using namespace std;


void swapByPointer(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

void swapByReference(int &a, int &b)
{
    int temp = a;
    a = b;
    b = temp;
}

int main()
{
    int var1 = 55;
    int var2 = 77;

    swapByPointer(&var1, &var2);

    cout << var1 << endl;
    cout << var2 << endl;

    swapByReference(var1, var2);

    cout << var1 << endl;
    cout << var2 << endl;
}

// ์‹คํ–‰๊ฒฐ๊ณผ
// 77
// 55
// 55
// 77

 

Call by Value์™€ Call by Reference๊ฐ€ ๋” ์ต์ˆ™ํ•˜๋‹ค. ์—ฌ๊ธฐ์„œ ๋ ˆํผ๋Ÿฐ์Šค๋Š” ์ฐธ์กฐ์ž๋ฅผ ์˜๋ฏธํ•œ๋‹ค๊ธฐ ๋ณด๋‹จ ๋” ๋„“์€ ๋ฒ”์œ„๋กœ ๊ฐ’๋งŒ ๋ณต์‚ฌ ํ•˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ, ์›๋ณธ ๊ฐ’์„ ์ฐธ์กฐํ•˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์“ฐ์ธ๋‹ค.

C++์—์„œ๋Š” Call by Reference์˜ ๋‘ ๊ฐ€์ง€, ํฌ์ธํ„ฐ์™€ ์ฐธ์กฐ์ž๋กœ ํ•จ์ˆ˜ ์ธ์ž ์ „๋‹ฌ ๋ฐฉ์‹์ด ์žˆ๊ณ  ๊ทธ ์ฐจ์ด๊ฐ€ ์œ„ ์ฝ”๋“œ์ด๋‹ค. ์ฝ”๋“œ๋Š” ๋ฌธ์ œ ์—†๋‹ค. 

 

์—ฌ๋Ÿฌ๋ถ„๋“ค์ด ๋ณด๊ธฐ์— ์–ด๋Š ์ชฝ์ด ๋” ๋ณด๊ธฐ ํŽธํ•˜๊ณ  ์“ฐ๊ธฐ ํŽธํ•œ๊ฐ€? 10๋ช… ์ค‘ 10๋ช…์€ ์ฐธ์กฐ์ž์— ์˜ํ•œ ๋ฐฉ์‹์ด ์ข‹๋‹ค๊ณ  ํ•  ๊ฒƒ์ด๋‹ค. ํฌ์ธํ„ฐ์ฒ˜๋Ÿผ ์ฃผ์†Œ๊ฐ’ ์—ฐ์‚ฐ์ž(&)์™€ ํฌ์ธํ„ฐ ๊ฐ’์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ์—ฐ์‚ฐ์ž(*)๋ฅผ ์“ธ ํ•„์š”๊ฐ€ ์—†๋‹ค.

 

์ฐธ์กฐ์ž์— ์˜ํ•œ ์ „๋‹ฌ ๋ฐฉ์‹์—์„œ ํŒŒ๋ผ๋ฏธํ„ฐ int &a, int &b๋Š” ์‹ค์ œ ์ „๋‹ฌ๋œ ์ธ์ž var1, var2๊ฐ€ ๋Œ€์ž…๋˜์„œ a, b๊ฐ€ ๊ฐ๊ฐ var1, var2๋ฅผ ์ฐธ์กฐ(๋ณ„๋ช… ์ƒ์„ฑ)ํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. ๋”ฐ๋ผ์„œ a, b๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด var1, var2๋Š” ๋‹น์—ฐํžˆ ๋ณ€๊ฒฝ๋œ๋‹ค.

 

 

โœ… ์ฐธ์กฐ์ž(Reference)์™€ ํฌ์ธํ„ฐ(Pointer)์˜ ์ฐจ์ด์ 

์ฐธ์กฐ์ž๊ฐ€ ๋‹จ์ˆœํžˆ ์“ฐ๊ธฐ ํŽธํ•ด์„œ ์“ฐ๋Š” ๊ฒƒ์ผ๊นŒ? ๊ทธ ์™ธ ํฌ์ธํ„ฐ์™€ ๋‹ค๋ฅธ ์ ์ด ํ•˜๋‚˜๋„ ์—†์„๊นŒ?

 

์ฐจ์ด์ ์ด ์žˆ๋‹ค.

 

โœ”๏ธ์ฒซ ๋ฒˆ์งธ, ์ฐธ์กฐ์ž๋Š” Null์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

์ฐธ์กฐ์ž๋Š” ์„ ์–ธ์‹œ ๋ฐ˜๋“œ์‹œ ์–ด๋–ค ๋Œ€์ƒ์„ ์ฐธ์กฐํ•ด์•ผ๋งŒ ํ•œ๋‹ค. int &ref; ํ˜น์€ int &ref = nullptr;์€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ๋ณดํ†ต ์šฐ๋ฆฌ๊ฐ€ ๋ณ„๋ช…์„ ์ง€์„ ๋•Œ ๋ณ„๋ช…๋ถ€ํ„ฐ ์ง€์–ด๋†“๊ณ  ๊ทธ ๋Œ€์ƒ์„ ์ฐพ์ง„ ์•Š๋Š”๋‹ค. ๋Œ€์ƒ์„ ์ƒ๊ฐํ•˜๋ฉด์„œ ๋ณ„๋ช…์„ ์ง“๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•˜๋‹ค.

์ด ๋ถ€๋ถ„์ด ์ฐธ์กฐ์ž๊ฐ€ ์•ˆ์ •์„ฑ์„ ๊ฐ–์ถ”๊ณ  ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. ํฌ์ธํ„ฐ๋Š” null์„ ํ—ˆ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, null์— ์ž˜๋ชป ์ ‘๊ทผํ•˜๋ฉด SIGSEGV๋ฅผ ๋งŒ๋‚˜๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ํฌ์ธํ„ฐ ๊ฐ’์˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ํ•ญ์ƒ ํ•ด์ค˜์•ผํ•˜์ง€๋งŒ ์ฐธ์กฐ์ž๋Š” ๊ทธ๋Ÿด ํ•„์š”๊ฐ€ ์—†๋‹ค.

 

โœ”๏ธ๋‘ ๋ฒˆ์งธ, ์ฐธ์กฐ์ž๋Š” ์ฐธ์กฐ ๋Œ€์ƒ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค.

ํฌ์ธํ„ฐ๋กœ ์„ ์–ธ๋œ ptr1์ด var1์„ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž. ptr1์ด var2๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ๋ณ€๊ฒฝํ–ˆ๋‹ค. ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค. ํ•˜์ง€๋งŒ ์ฐธ์กฐ์ž๋Š” ์ด๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ๋ณด์ž.

#include <iostream>

using namespace std;

int main()
{
    int var1 = 5;
    int var2 = 3;

    int &ref1 = var1;
    ref1 = var2;
	
    cout << &var1 << endl;
    cout << &var2 << endl;
    cout << &ref1 << endl;
    
    cout << var1 << endl;
    cout << var2 << endl;
    cout << ref1 << endl;
}
// ์‹คํ–‰๊ฒฐ๊ณผ
// 000CA683
// 000CF42B
// 000CA683
// 3
// 3
// 3

๋งŒ์•ฝ ref1์ด ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ๋ณ€์ˆ˜๋ฅผ var2๋กœ ๋ฐ”๊พธ๋ ค๊ณ  ref1 = var2๋ฅผ ํ•˜๋ฉด ์˜๋„ํ•œ ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ด๋Š” var1 = var2๋ฅผ ์‹คํ–‰ํ•œ ์…ˆ์ด ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ์—ฌ์ „ํžˆ ref1์€ var1๊ณผ ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ์ฃผ์†Œ๋ฅผ ๊ฐ–๊ณ  ์žˆ๊ณ , ๊ฐ’๋งŒ 5์—์„œ 3์œผ๋กœ ๋ณต์‚ฌ๋˜์—ˆ๋‹ค.

ํ˜น์‹œ ํ—ท๊ฐˆ๋ฆฐ๋‹ค๋ฉด ref1์„ ๋ชจ๋‘ var1๋กœ ๋ฐ”๊ฟ” ๋ณด๋ฉด ์ดํ•ด๊ฐ€ ๋น ๋ฅผ ๊ฒƒ์ด๋‹ค.(์ด๋ฆ„๊ณผ ๋ณ„๋ช…์€ ๋™์ผํ•œ ์‚ฌ๋žŒ์ด๋‹ˆ๊นŒ)

 

โœ”๏ธ์„ธ ๋ฒˆ์งธ, ์ฐธ์กฐ์ž๋Š” ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์†Œ๋ชจํ•˜์ง€ ์•Š๋Š”๋‹ค.

ํฌ์ธํ„ฐ๋Š” ์ฃผ์†Œ ๊ฐ’์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด ๋ณ„๋„์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์†Œ๋ชจํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ฐธ์กฐ์ž๋Š” ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์ฐธ์กฐํ•˜๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์†Œ๋ชจํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

์ด๋Š” Call by Reference์—์„œ๋„ ์ธ์ž ์ „๋‹ฌ์— ์˜ํ•œ ๋ฉ”๋ชจ๋ฆฌ ์†Œ๋ชจ๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ ์ธก๋ฉด์—์„œ๋„ ํฌ์ธํ„ฐ๋ณด๋‹ค ํšจ์œจ์ ์ด๋‹ค.

 

 

โœ… ์‹ค๋ฌด์—์„œ์˜ ์ฐธ์กฐ์ž ์‚ฌ์šฉ

// Function Parameter
inline void updateLastPrices(const std::string& symbol, const std::pair<double, double>& prices)
{
    std::lock_guard<std::mutex> lk(lastPricesMx);
    lastPrices[symbol] = prices;
}

// Reference
for (const auto& elem : Data)
{
    const auto& type = elem.firstReq.detail.type;
    auto& ticket = elem.firstReq.detail.ticket;

    if ( type == CHANGE )
    {
        ticket += 10;
    }
}

์‹ค๋ฌด์—์„œ๋Š” Call by Reference๋ฅผ ๋งค์šฐ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค. ์–ด์ฉ” ์ˆ˜ ์—†์ด ํฌ์ธํ„ฐ๋ฅผ ๋„˜๊ฒจ์•ผ ํ•  ๋•Œ๋ฅผ ์ œ์™ธํ•˜๊ณ ๋Š” ๋Œ€๋ถ€๋ถ„์˜ ํด๋ž˜์Šค ์ธํ„ด์Šค๋ฅผ ์ฐธ์กฐ์ž๋กœ ๋„˜๊ธด๋‹ค.

์—ฌ๊ธฐ์„œ ์ž์ฃผ ์“ฐ๋Š” ํŒจํ„ด์€, INPUT๊ฐ’์€ const XXXX&, OUTPUT๊ฐ’์€ XXXX& ํ˜•ํƒœ๋กœ ๋„˜๊ธด๋‹ค. ์ฆ‰, ๊ฐ’์— ์˜ํ•œ ๋ณต์‚ฌ๊ฐ€ ์ด๋ฃจ์–ด์ง€์ง€ ์•Š๋„๋ก ์ฐธ์กฐ์ž๋ฅผ ์“ฐ๋˜, const๋ฅผ ๋ถ™์—ฌ์„œ ์ƒ์ˆ˜์ž„์„ ๋ณด์žฅํ•˜๊ณ , ์›๋ณธ ๊ฐ’์˜ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ const๋ฅผ ๋ถ™์ด์ง€ ์•Š๋Š” ๋ฐฉ์‹์ด๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ์ฐธ์กฐ์ž๋ฅผ ๋ณ„์นญ์ฒ˜๋Ÿผ ์“ฐ๋Š” ๋ฐฉ์‹์ด ์žˆ๋‹ค.(์ฝ”๋“œ์—์„œ Reference๋ถ€๋ถ„). elem.firstReq.detail.XXXX์™€ ๊ฐ™์ด ๋ณ€์ˆ˜๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ํด๋ž˜์Šค ํ˜•ํƒœ๋กœ ๋ฉค๋ฒ„๋ณ€์ˆ˜๋ฅผ ๊ฐ€์งˆ ๋•Œ ์ฐธ์กฐ์ž๋กœ ํ•ด๋‹น ๋ณ€์ˆ˜๋ฅผ ๋ณ„๋ช…์œผ๋กœ ๋งŒ๋“ ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ํŽธํ•˜๊ฒŒ ์ค„์—ฌ์„œ type, ticket๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ type์€ ๋ณ€๊ฒฝ๋  ์ผ์ด ์—†์œผ๋ฏ€๋กœ const auto& type; ์œผ๋กœ ํ‘œํ˜„ํ–ˆ๊ณ , ticket์€ ๋ณ€๊ฒฝ์ด ์žˆ์œผ๋ฏ€๋กœ const๋ฅผ ๋บ๋‹ค.

 

 

์ด์ฒ˜๋Ÿผ ์ฐธ์กฐ์ž๋Š” ์›๋ณธ ๊ฐ’์˜ ๋ณ€๊ฒฝ์ด ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” const๋ฅผ ๋ถ™์ด๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

 

 

๋Œ“๊ธ€