๐ ํฌ์ธํฐ์ ๋ ํผ๋ฐ์ค โ ์ฐจ์ด์ ๋ถ์
Notion ์๋ณธ: https://www.notion.so/348f77b24d2f80c4ace7e1eae457d555 ๋ถ๋ชจ: ์๋ฃ โ Cs ๋ฉด์ ์ค๋น โ cs ์ฃผ์ ์ ๋ฆฌ ๊ธฐ์ค์ผ: 2026-04-20
ํ ์ค ์ ์
- ํฌ์ธํฐ (
T*) โ ์ด๋ค ๊ฐ์ฒด์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ์ ์ฅํ๋ ๋ณ์. ์ฃผ์ ์์ฒด๊ฐ ๊ฐ์ด๋ผ ์ฌํ ๋นยท์ฐ์ ์ฐ์ฐยทnullptr์ด ๊ฐ๋ฅํ๋ค. - ๋ ํผ๋ฐ์ค (
T&) โ ์ด๋ฏธ ์กด์ฌํ๋ ๊ฐ์ฒด์ ๋ ๋ค๋ฅธ ์ด๋ฆ(๋ณ์นญ). ์ ์ธ ์ ๋ฐ๋์ ์๋ณธ๊ณผ ๋ฌถ์ด๊ณ ์ดํ ๋ถ๋ฆฌ ๋ถ๊ฐ.
ํฌ์ธํฐ๋ โ์ฃผ์โ๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ณ์, ๋ ํผ๋ฐ์ค๋ โ๊ทธ ์์ฒดโ๋ฅผ ๊ฐ๋ฆฌํค๋ ์ด๋ฆ๋ง ๋ฐ๋ ์ํ.
์ฐจ์ด์ ๋น๊ตํ
| ํญ๋ชฉ | ํฌ์ธํฐ (T*) | ๋ ํผ๋ฐ์ค (T&) |
|---|
| ์ ์ธ ์ ์ด๊ธฐํ | ์๋ต ๊ฐ๋ฅ (T* p;) | ํ์ (T& r = x;) |
| nullptr ํ์ฉ | ๊ฐ๋ฅ (T* p = nullptr;) | ๋ถ๊ฐ โ ์ ํจํ ๊ฐ์ฒด ํ์ |
| ์ฌํ ๋น | ๊ฐ๋ฅ (p = &y;) | ๋ถ๊ฐ โ ์๋ช
๋์ ๋์ผ ๊ฐ์ฒด |
| ์ญ์ฐธ์กฐ ๋ฌธ๋ฒ | *p ๋ช
์ ํ์ | ์๋ (r ์์ฒด๊ฐ ์๋ณธ์ฒ๋ผ) |
| ๋ฉค๋ฒ ์ ๊ทผ | p->member | r.member |
| ์ฐ์ ์ฐ์ฐ | ๊ฐ๋ฅ (p++, p + 1) | ๋ถ๊ฐ |
| ๋ฐฐ์ด ๋์ฒด | T[]์ ํธํ | ๋ถ๊ฐ |
| ๋ฉ๋ชจ๋ฆฌ ์ ์ | ์ฃผ์๊ฐ ํฌ๊ธฐ (๋ณดํต 8byte) | ๊ตฌํ์ ๋ฐ๋ผ ๋ค๋ฆ |
| ๋คํ์ฑ | ๊ฐ๋ฅ | ๊ฐ๋ฅ |
์ ์ธ๊ณผ ์ด๊ธฐํ
1
2
3
4
5
6
7
8
9
| int x = 10, y = 20;
// ํฌ์ธํฐ โ ์ด๊ธฐํ ์๋ต ๊ฐ๋ฅ
int* p; // โ ๏ธ ์ฐ๋ ๊ธฐ ์ฃผ์, ์ ๋ ์ญ์ฐธ์กฐ ๊ธ์ง
int* p2 = &x; // x์ ์ฃผ์๋ก ์ด๊ธฐํ
// ๋ ํผ๋ฐ์ค โ ๋ฐ๋์ ์ด๊ธฐํ
int& r = x; // x์ ๋ณ์นญ
int& r2; // โ ์ปดํ์ผ ์๋ฌ
|
ํต์ฌ: ๋ ํผ๋ฐ์ค๋ โ๋์ ์๋ ๋ ํผ๋ฐ์คโ๊ฐ ๋ฌธ๋ฒ์ ์ผ๋ก ๋ถ๊ฐ๋ฅ โ ํญ์ ์ ํจํ ๋์์ด ๋ณด์ฅ๋๋ค๋ ์ ์ด ํจ์ ์ธ์์์ ๊ฐ๋ ฅํ ์์ ์ฑ์ ์ ๊ณต.
์ฌํ ๋น ๊ฐ๋ฅ์ฑ
1
2
3
4
5
6
7
8
9
| int a = 10, b = 20;
// ํฌ์ธํฐ โ ๊ฐ๋ฆฌํค๋ ๋์ ๋ณ๊ฒฝ ๊ฐ๋ฅ
int* p = &a;
p = &b; // โ
์ด์ p๋ b๋ฅผ ๊ฐ๋ฆฌํด
// ๋ ํผ๋ฐ์ค โ ํ ๋ฒ ๋ฌถ์ด๋ฉด ๋
int& r = a;
r = b; // โ ๏ธ ์ฌํ ๋น์ด ์๋๋ผ "a = b" ์ ๋์ผ (๊ฐ ๋ณต์ฌ)
|
r = b;๋ ๋ ํผ๋ฐ์ค๊ฐ b๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ๋ฐ๊พธ๋ ๊ฒ ์๋๋ผ, r์ด ์ฐธ์กฐํ๋ ์๋ณธ(a)์ b์ ๊ฐ์ ๋์
ํ๋ค. ๋ ํผ๋ฐ์ค๋ ํ๋ฒ ๋ฌถ์ด๋ฉด ์ ๋ ๋ค๋ฅธ ๊ฐ์ฒด๋ก ์ฎ๊ธธ ์ ์๋ค.
์ญ์ฐธ์กฐ ๋ฌธ๋ฒ
1
2
3
4
5
6
7
8
9
10
11
| int x = 5;
// ํฌ์ธํฐ โ ๋ช
์์ ์ญ์ฐธ์กฐ
int* p = &x;
*p = 10;
cout << *p; // 10
// ๋ ํผ๋ฐ์ค โ ์๋
int& r = x;
r = 10;
cout << r; // 10
|
๊ตฌ์กฐ์ฒด ์ ๊ทผ:
1
2
3
4
5
6
7
8
9
| struct Item { int id; };
Item i{42};
Item* p = &i;
p->id = 100; // -> ์ฐ์ฐ์
(*p).id = 100; // ๋์ผ (์ญ์ฐธ์กฐ ํ .)
Item& r = i;
r.id = 100; // . ์ฐ์ฐ์
|
nullptr / NULL
1
2
3
4
5
6
7
| T* p = nullptr; // โ
์ ํจ
T& r = *p; // ๐ฅ UB โ null ์ญ์ฐธ์กฐ
// ์์ ํจํด
if (p != nullptr) {
p->doSomething();
}
|
์ ๋ ํผ๋ฐ์ค๋ nullptr์ด ์๋๊ฐ?
- ๋ ํผ๋ฐ์ค๋ โ๊ฐ์ฒด์ ๋ณ์นญโ์ด๋ผ๋ ์๋ฏธ๋ก ์ ๋ฌถ์ฌ ์์ด์ ๋์ ์๋ ์ํ๊ฐ ์กด์ฌํ ์ ์์
- ํจ์ ์ธ์๋ก ๋ ํผ๋ฐ์ค๋ฅผ ๋ฐ์ผ๋ฉด
nullptr ์ฒดํฌ ๋ถํ์ - ๋จ,
T& r = *nullptr; ๊ฐ์ ์ฝ๋๋ก ๋ฌดํจํ ๋ ํผ๋ฐ์ค๋ฅผ ๋ง๋ค ์๋ ์์ง๋ง ์ด๋ UB
ํจ์ ๋งค๊ฐ๋ณ์๋ก ์ฌ์ฉ
ํฌ์ธํฐ ๋ฒ์
1
2
3
4
5
6
| void setPotion(int count, int* p_HPPotion, int* p_MPPotion) {
*p_HPPotion = count; // ์ญ์ฐธ์กฐ ํ์
*p_MPPotion = count;
}
setPotion(5, &HPPotion, &MPPotion); // ํธ์ถ๋ถ์ & ํ์
|
๋ ํผ๋ฐ์ค ๋ฒ์
1
2
3
4
5
6
| void setPotion(int count, int& HPPotion, int& MPPotion) {
HPPotion = count; // ์ญ์ฐธ์กฐ ์์
MPPotion = count;
}
setPotion(5, HPPotion, MPPotion); // ํธ์ถ๋ถ๊ฐ ๊น๋
|
const ๋ ํผ๋ฐ์ค โ ์ฝ๊ธฐ ์ ์ฉ ํจ์จ
1
2
3
4
| void InitWeapon(const FWeaponData& InData, const FWeaponAssets& InAssets)
{
// ๋ณต์ฌ ๋น์ฉ ์์ด ์ฝ๊ธฐ๋ง โ ๊ฐ์ฅ ํํ ์ฐ๋ ํจํด
}
|
์ ํ ๊ธฐ์ค:
| ์ํฉ | ์ถ์ฒ |
|---|
| ๋ฐ๋์ ์ ํจํ ๊ฐ์ฒด๋ง ๋ฐ์ | ๋ ํผ๋ฐ์ค |
| โ์์ ์๋ ์์โ์ ํํ | ํฌ์ธํฐ (nullptr) |
| ์ฝ๊ธฐ ์ ์ฉ ํฐ ๊ฐ์ฒด | const T& |
| ์์ ๊ถ ์ด์ | std::unique_ptr<T> (์ด๋) |
ํด๋์ค ๋ฉค๋ฒ์์ ์ฌ์ฉ
1
2
3
4
5
6
| class APlayer
{
AWeapon* CurrentWeapon; // โ
์ฅ์ฐฉ ์ ์๋ nullptr ๊ฐ๋ฅ
AWorld& World; // โ ๏ธ ์ด๊ธฐํ ๋ฆฌ์คํธ์์ ๋ฐ๋์ ๋ฌถ์ด์ผ ํจ
// + ๋ณต์ฌ/๋์
์ฐ์ฐ์ ์์ฑ ๊ณค๋
};
|
๋ ํผ๋ฐ์ค ๋ฉค๋ฒ์ ์ ์ฝ:
- ์์ฑ์ ์ด๊ธฐํ ๋ฆฌ์คํธ์์ ๋ฐ๋์ ์ด๊ธฐํ
- ์ดํ ๋ค๋ฅธ ๊ฐ์ฒด๋ก ์ฌํ ๋น ๋ถ๊ฐ โ ๊ธฐ๋ณธ ๋์
์ฐ์ฐ์ ์๋ ์ญ์
- ์์ ๊ด๊ณ๊ฐ ์๋๋ผ โํ์ ๊ฐ์ด ๋ค๋๋ ์ฐ๊ด ๊ฐ์ฒดโ์ผ ๋๋ง ๊ถ์ฅ
์ค๋ฌด์์๋ ๋ฉค๋ฒ๋ก ํฌ์ธํฐ๋ฅผ ์ฐ๋ ๊ฒ์ด ํจ์ฌ ์ ์ฐ.
๋คํ์ฑ๊ณผ ๋์ ๋์คํจ์น
๋ ๋ค ๋คํ์ฑ์ ์ง์ํ๋ค โ ํต์ฌ์ โ์ด๋ป๊ฒ ๊ฐ์ฒด๋ฅผ ์ก๊ณ ์๋๋โ๊ฐ ์๋๋ผ โ์ก์ ๊ฐ์ฒด๊ฐ virtual ํจ์๋ฅผ ๊ฐ์ง๋๋โ.
1
2
3
4
5
6
7
8
9
10
11
| // ํฌ์ธํฐ ๋ฒ์
Player* player = new Warrior(nickname);
player->attack(); // ์์ attack() ํธ์ถ
Player* player2 = new Magician(nickname);
player2->attack(); // ๋ค๋ฅธ ์์์ attack()
// ๋ ํผ๋ฐ์ค ๋ฒ์
Warrior w("Lupang");
Player& ref = w;
ref.attack(); // ์์ attack() โ ๋์ผํ๊ฒ ๋์
|
๊ฐ์ ์๋ฉธ์ ํ์: delete player; ๊ฐ ์์ ์๋ฉธ์๋ฅผ ํธ์ถํ๋ ค๋ฉด ๋ถ๋ชจ๊ฐ virtual ~Player()๋ก ์ ์ธ. ๋ ํผ๋ฐ์ค๋ delete ๋ถ๊ฐ๋ผ ์ด ๋ฌธ์ ๊ฐ ์๋ค.
๋ฐฐ์ด๊ณผ ํฌ์ธํฐ ์ฐ์ฐ
1
2
3
4
5
6
7
8
9
10
| int arr[5] = {1, 2, 3, 4, 5};
int* p = arr; // ๋ฐฐ์ด ์ด๋ฆ์ด ํฌ์ธํฐ๋ก ์๋ ๊ฐ์ (decay)
// ํฌ์ธํฐ ์ฐ์
p[2] = 30; // arr[2]
*(p + 2) = 30; // ๋์ผ
p++; // p๊ฐ ๋ค์ ์์
// ๋ ํผ๋ฐ์ค โ ๋ฐฐ์ด ์ ์ฒด ์ฐธ์กฐ
int (&rArr)[5] = arr; // ํฌ๊ธฐ ์ ๋ณด ์ ์ง
|
์ธ๋ฆฌ์ผ์์์ ํฌ์ธํฐ
์์ ํฌ์ธํฐ vs TObjectPtr
| ์ํฉ | ๊ถ์ฅ | ์ด์ |
|---|
ํค๋์์ UPROPERTY() ๋ฉค๋ฒ ๋ณ์ | TObjectPtr<T> | ์ง์ฐ ๋ก๋ฉ + ์ก์ธ์ค ํธ๋ํน |
| ์ง์ญ ๋ณ์, ๋งค๊ฐ๋ณ์ | T* ์์ ํฌ์ธํฐ | ํธ๋ํน ์ค๋ฒํค๋ ๋ถํ์ |
1
2
3
4
5
6
7
8
9
| // UE5 ๊ถ์ฅ
UPROPERTY(EditAnywhere)
TObjectPtr<USceneComponent> RootComp;
// ์ง์ญ ๋ณ์๋ ์์ ํฌ์ธํฐ
void UseComp() {
USceneComponent* Local = RootComp;
Local->SetVisibility(false);
}
|
๋ฐ๋ณต๋ฌธ์์ auto* ๋์ auto&
1
2
3
4
5
6
7
| TArray<TObjectPtr<USceneComponent>> Components;
// โ ๋งค ๋ฐ๋ณต๋ง๋ค TObjectPtr ๋ด๋ถ ๋ก์ง ์ฌ์คํ
for (auto* Component : Components) { }
// โ
๋ฐฐ์ด ์ TObjectPtr ์์ฒด๋ฅผ ์ฐธ์กฐ๋ง ํจ
for (auto& Component : Components) { }
|
ํต์ฌ ์๋ฆฌ: ํฌ์ธํฐ๋ ์ฃผ์๋ฅผ ๋ณต์ฌํด์ค๋ ๊ฒ, ๋ ํผ๋ฐ์ค๋ ์๋ณธ์ ๊ทธ๋๋ก ๊ฐ์ ธ๋ค ์ โ ์ด ์ฐจ์ด๋ก TObjectPtr ๋ด๋ถ ๋ก์ง์ด ํ ๋ฒ ๋ ๋์ง ์๋๋ค.
UPROPERTY์ ์ญํ
1
2
3
4
| UPROPERTY() // GC๊ฐ ์ด ํฌ์ธํฐ๋ฅผ ์ถ์ โ ์๊ฑฐ ์ ๋จ
UMyComponent* SafeComp;
UMyComponent* DangerousComp; // UPROPERTY ์์ โ GC๊ฐ ์๊ฑฐ ๊ฐ๋ฅ โ ๋๊ธ๋ง ํฌ์ธํฐ
|
TSubclassOf
ํด๋์ค๋ฅผ ๋ด๋ ๋ฐ๊ตฌ๋ โ ๋ ๋ฒจ ์ธ์คํด์ค๋ฅผ ๊ฐ๋ฆฌํค๋ TObjectPtr๊ณผ ๋ค๋ฅด๊ฒ โClass ์์ฒดโ๋ฅผ ๋ด๋ ํ์
์์ ํฌ์ธํฐ.
1
2
| UPROPERTY(EditAnywhere)
TSubclassOf<UActorComponent> CompClass;
|
์ค๋งํธ ํฌ์ธํฐ์ ์ํ ์ฐธ์กฐ
1
2
3
4
5
6
7
8
9
| struct Node {
shared_ptr<Node> next;
shared_ptr<Node> prev;
};
auto a = make_shared<Node>(); // ref = 1
auto b = make_shared<Node>(); // ref = 1
a->next = b; // b ref = 2
b->prev = a; // a ref = 2
// a, b ์๋ฉธ ์ ref 2 โ 1 โ ์์ํ 0 ์ ๋จ โ ๋ฉ๋ชจ๋ฆฌ ๋์
|
ํด๊ฒฐ: ํ์ชฝ์ weak_ptr๋ก
1
2
3
4
| struct Node {
shared_ptr<Node> next; // ๊ฐํ ์ฐธ์กฐ
weak_ptr<Node> prev; // ์ฝํ ์ฐธ์กฐ
};
|
| ย | shared_ptr | weak_ptr |
|---|
| ์ฐธ์กฐ ์นด์ดํธ ์ฆ๊ฐ | โ
| โ |
| ๊ฐ์ฒด ์๋ช
์ฐ์ฅ | โ
| โ |
| ์ํ ์ฐธ์กฐ | ์ ๋ฐ | ํด๊ฒฐ์ฑ
|
ํ์ฉ ์์น: ์๋ฐฉํฅ ์ฐ๊ฒฐ(์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ, ๋ถ๋ชจโ์์)์์ ํ์ชฝ์ ๋ฐ๋์ weak_ptr๋ก ์ฌ์ฉ.
์ฃผ์ ํค์๋ ์์ฝ
๋ฌธ๋ฒ ์์ค
& โ ์ฃผ์ ์ฐ์ฐ์ / ๋ ํผ๋ฐ์ค ์ ์ธ (์์น๋ก ๊ตฌ๋ถ)* โ ํฌ์ธํฐ ์ ์ธ / ์ญ์ฐธ์กฐ ์ฐ์ฐ์ (์์น๋ก ๊ตฌ๋ถ)-> โ ํฌ์ธํฐ์ ๋ฉค๋ฒ ์ ๊ทผnullptr โ ํฌ์ธํฐ ์ ์ฉ, ๋ ํผ๋ฐ์ค์๋ ์์
์๋ช
ยท์๋ณ
- ํฌ์ธํฐ = ์ฃผ์๋ฅผ ๋ด๋ ๋ณ์ (๋
๋ฆฝ๋ ์ ์ฅ์ ์กด์ฌ)
- ๋ ํผ๋ฐ์ค = ๋ณ์นญ (alias) (์๋ณธ๊ณผ ๋์ผ ๊ฐ์ฒด)
- ๋ ํผ๋ฐ์ค๋ ์ด๊ธฐํ ์์ 1ํ ๋ฐ์ธ๋ฉ โ ์ฌํ ๋น ๋ถ๊ฐ
ํจ์ ์ธ์ ์ ํ ๊ท์น
| ์๊ตฌ | ์ ํ |
|---|
| ๊ฐ ์์ , ์ ํจ์ฑ ๋ณด์ฅ | T& |
| ์ฝ๊ธฐ ์ ์ฉ, ์ ํจ์ฑ ๋ณด์ฅ | const T& |
| ๊ฐ ์์ , โ์์ ์๋โ ํ์ฉ | T* |
| ์์ ๊ถ ์ด์ | std::unique_ptr<T> + std::move |
์ธ๋ฆฌ์ผ ํ์ฅ
UPROPERTY() ์๋ UObject ํฌ์ธํฐ = GC ์๊ฑฐ โ ์ฌ์ฉ ๊ธ์ง- ํค๋ UPROPERTY ๋ฉค๋ฒ๋
TObjectPtr<T> ๊ถ์ฅ - ์ง์ญ ๋ณ์ยท๋งค๊ฐ๋ณ์๋ ์์ ํฌ์ธํฐ๊ฐ ํจ์จ์
- ํด๋์ค๋ฅผ ๋ด์ ๋๋
UClass* ๋์ TSubclassOf<T> TArray<TObjectPtr<T>> ์ํ๋ auto&๋ก
์ค๋งํธ ํฌ์ธํฐ
shared_ptr โ ์ฐธ์กฐ ์นด์ดํธ ๊ธฐ๋ฐ ๊ณต์ ์์ ๊ถunique_ptr โ ๋จ๋
์์ ๊ถ, ์ด๋ ์ ์ฉweak_ptr โ ์นด์ดํธ ์ฆ๊ฐ ์๋ ์ฝํ ๊ด์ฐฐ์, ์ํ ์ฐธ์กฐ ๋๊ธฐ์ฉ
๋ณต๊ธฐ
- ํฌ์ธํฐ๋ โ์ด๋ ์๋์งโ, ๋ ํผ๋ฐ์ค๋ โ๊ทธ ์์ฒดโ โ ์ด ํ ๋ฌธ์ฅ์ด ๋ฌธ๋ฒยท๋์ ์ฐจ์ด์ ๋ชจ๋ ๋ฟ๋ฆฌ
const T&๋ C++์์ ๊ฐ์ฅ ์์ฃผ ์ฐ๋ ํจ์ ์ธ์ ํจํด- UE5๋ ์์
UObject* ๋์ TObjectPtr<T>์ ๋ฐ์ง๋ง, ์ง์ญ ๋ณ์๋ ์ฌ์ ํ ์์ ํฌ์ธํฐ๊ฐ ๋น ๋ฆ auto* ๋์ auto&๋ฅผ ์ฐ๋ ์ด์ ๋ โTObjectPtr ๊ฐ์ ๋น์ฉโ ๋๋ฌธ- ์ํ ์ฐธ์กฐ ์ํฉ์์ โ์์ชฝ ๋ชจ๋ shared_ptr โ ๋์โ๋ ๋ฉด์ ๋จ๊ณจ โ ํ์ชฝ์ weak_ptr๋ก ๋๋ ํจํด ์๊ธฐ