CS โ class vs struct
๐ class์ struct ์ ์ฐจ์ด์
Notion ์๋ณธ: https://www.notion.so/344f77b24d2f8029867ff8e37968ce24 ๋ถ๋ชจ: ์๋ฃ โ Cs ๋ฉด์ ์ค๋น โ cs ์ฃผ์
๋ชจ์๋ฉด์ ๋ต๋ณ
C++์์ class์ struct์ ๊ธฐ๋ฅ์ ์ฐจ์ด๋ ๋ฑ ๋ ๊ฐ์ง์ ๋๋ค. ์ฒซ์งธ, ๊ธฐ๋ณธ ์ ๊ทผ ์ง์ ์๊ฐ ๋ค๋ฆ ๋๋ค. struct๋ public์ด ๊ธฐ๋ณธ์ด๊ณ , class๋ private์ด ๊ธฐ๋ณธ์ ๋๋ค. ๋์งธ, ๊ธฐ๋ณธ ์์ ๋ฐฉ์์ด ๋ค๋ฆ ๋๋ค. struct๋ public ์์, class๋ private ์์์ด ๊ธฐ๋ณธ์ ๋๋ค. ์ด ์ธ์ ๋ฉค๋ฒ ํจ์, ์์ฑ์, ์๋ฉธ์, ์์, ํ ํ๋ฆฟ ๋ฑ ๋ชจ๋ ๊ธฐ๋ฅ์ ์์ ํ ๋์ผํฉ๋๋ค. ๊ด์ฉ์ ์ผ๋ก๋ ๋ฐ์ดํฐ๋ง ๋ฌถ๋ ๋จ์ ์งํฉ์ฒด์๋ struct๋ฅผ, ์บก์ํ์ ์ ๋ณด ์๋์ด ํ์ํ ํ์ ์๋ class๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ถ๊ฐ๋ก ํ ํ๋ฆฟ ๋งค๊ฐ๋ณ์์์๋ class๋ typename์ ์ฌ์ฉํ ์ ์์ง๋ง, struct๋ ์ฌ์ฉํ ์ ์๋ค๋ ์ฐจ์ด๋ ์์ต๋๋ค.
ํต์ฌ ๊ฐ๋
- ๊ธฐ๋ณธ ์ ๊ทผ ์ง์ ์ (Default Access Specifier) โ struct๋
public, class๋private์ด ๊ธฐ๋ณธ - ๊ธฐ๋ณธ ์์ ๋ฐฉ์ (Default Inheritance) โ struct๋
public์์, class๋private์์์ด ๊ธฐ๋ณธ - ์บก์ํ (Encapsulation) โ ๋ฐ์ดํฐ์ ํจ์๋ฅผ ํ๋๋ก ๋ฌถ๊ณ ์ธ๋ถ ์ ๊ทผ์ ์ ์ดํ๋ OOP ์์น
- ์ ๋ณด ์๋ (Information Hiding) โ ๋ด๋ถ ๊ตฌํ์ ์จ๊ธฐ๊ณ public ์ธํฐํ์ด์ค๋ง ๋ ธ์ถ
- POD (Plain Old Data) โ ๋จ์ ๋ฐ์ดํฐ ์งํฉ์ฒด. Trivial + Standard-layout ์กฐ๊ฑด ์ถฉ์กฑ ํ์
- ํ
ํ๋ฆฟ ๋งค๊ฐ๋ณ์ (Template Parameter) โ
template<class T>,template<typename T>๋ ๊ฐ๋ฅํ์ง๋งtemplate<struct T>๋ ์ปดํ์ผ ์๋ฌ
์์ธ ๋น๊ต
๊ธฐ๋ณธ ์ ๊ทผ ์ง์ ์
1
2
3
4
5
6
7
8
9
struct MyStruct {
int x; // public (๊ธฐ๋ณธ๊ฐ)
void foo() {}
};
class MyClass {
int x; // private (๊ธฐ๋ณธ๊ฐ)
void foo() {}
};
๊ธฐ๋ณธ ์์ ๋ฐฉ์
1
2
3
4
5
struct DerivedS : Base { }; // public ์์ (๊ธฐ๋ณธ)
class DerivedC : Base { }; // private ์์ (๊ธฐ๋ณธ)
struct S : public Base { };
class C : public Base { };
๊ด์ฉ์ ์ฌ์ฉ ๊ตฌ๋ถ
- struct: ๋ฐ์ดํฐ๋ง ๋ฌถ๋ ๋จ์ ์งํฉ์ฒด (POD), ์ขํยท์์ยท์ค์ ๊ฐ ๋ฌถ์
- class: ์บก์ํยท์ ๋ณด ์๋์ด ํ์ํ ํ์ , PlayerยทItemยทManager ๋ฑ
C vs C++: C์
struct๋ ํจ์ ๋ฉค๋ฒ ๋ถ๊ฐ. C++์์๋struct์๋ ์์ฑ์ยท์๋ฉธ์ยท๋ฉค๋ฒ ํจ์ ๋ชจ๋ ๊ฐ๋ฅ
ํ ํ๋ฆฟ ๋งค๊ฐ๋ณ์์์์ ์ฐจ์ด
1
2
3
template <class T> // OK
template <typename T> // OK
template <struct T> // โ ์ปดํ์ผ ์๋ฌ
์ struct๋ ํ ํ๋ฆฟ ๋งค๊ฐ๋ณ์๋ก ์ฌ์ฉํ ์ ์๋๊ฐ:
- C++ ํ์ค ๋ช
์ธ [temp.param]์
class identifier๋๋typename identifier๋ ํํ๋ก๋ง ์ ์ - ์ญ์ฌ์ ๋ฐฐ๊ฒฝ โ ์ด๊ธฐ C++๋
class๋ง, C++98์์typename์ถ๊ฐ (์๋ฏธ์ ๋ณด์),struct๋ ์ถ๊ฐ ๋๊ธฐ ์์ - ์๋ฏธ์ ์ค๋ณต ํํผ โ ํ ํ๋ฆฟ ๋งค๊ฐ๋ณ์์์ class๋ โ์์์ ํ์ โ์ด๋ผ ์ ๊ทผ ์ง์ ์์ ๋ฌด๊ด
- ์ธ์ด ์ผ๊ด์ฑ โ
class์typename๋ง์ผ๋ก ์ถฉ๋ถ
Aggregate ์ด๊ธฐํ (C++17~)
1
2
3
4
5
6
7
8
9
10
11
12
13
struct Point { int x; int y; }; // aggregate
Point p = {10, 20}; // OK
class Pos {
public:
int x; int y;
};
Pos q = {10, 20}; // OK
class Hidden {
int x; int y; // private โ aggregate ์๋
};
// Hidden h = {10, 20}; // โ ์ปดํ์ผ ์๋ฌ
๊ผฌ๋ฆฌ๋ฌผ๊ธฐ ์์ ์ง๋ฌธ
Q1. struct์ ์์ฑ์๋ฅผ ์ ์ํ๋ฉด POD๊ฐ ๋๋์?
์๋์. ์ฌ์ฉ์ ์ ์ ์์ฑ์๊ฐ ์์ผ๋ฉด trivial ์์ฑ์ ์กฐ๊ฑด์ด ๊นจ์ ธ POD๊ฐ ์๋๋๋ค. POD = Trivial + Standard-layout ๋ ์กฐ๊ฑด์ ๋ชจ๋ ์ถฉ์กฑํด์ผ ํฉ๋๋ค.
1
2
struct A { A() {} }; // ์ฌ์ฉ์ ์ ์ ์์ฑ์ โ trivial ์๋ โ POD ์๋
struct B { int x; int y; }; // ๊ธฐ๋ณธ ์์ฑ์ โ trivial โ POD
Q2. struct์ class์ ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์์ด ๋ค๋ฅธ๊ฐ์?
๊ธฐ๋ณธ์ ์ผ๋ก ๋์ผํ ๋ฐฉ์์ผ๋ก ํจ๋ฉ์ด ์ ์ฉ๋ฉ๋๋ค. ๋จ, ์ ๊ทผ ์ง์ ์๊ฐ ๋ค๋ฅธ ๋ฉค๋ฒ ์ฌ์ด์ ์์๋ ํ์ค์์ ๋ณด์ฅํ์ง ์์ต๋๋ค. ๊ฐ์ ์ ๊ทผ ์ง์ ์ ๋ด์์๋ ์ ์ธ ์์๊ฐ ๋ณด์ฅ๋ฉ๋๋ค.
Q3. union๊ณผ struct์ ์ฐจ์ด๋?
- struct: ๊ฐ ๋ฉค๋ฒ๊ฐ ๋ณ๋์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น โ ํฌ๊ธฐ = ๋ชจ๋ ๋ฉค๋ฒ ํฉ + ํจ๋ฉ
- union: ๋ชจ๋ ๋ฉค๋ฒ๊ฐ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณต์ โ ํฌ๊ธฐ = ๊ฐ์ฅ ํฐ ๋ฉค๋ฒ
- union์ ํ ๋ฒ์ ํ๋์ ๋ฉค๋ฒ๋ง ์ ํจ (๋์ ์ ๊ทผ ์ UB)
Q4. C++ Core Guidelines์์ struct์ class ์ฌ์ฉ ๊ธฐ์ค์?
๋ถ๋ณ์(invariant)์ด ์๋ ๋จ์ ๋ฐ์ดํฐ ๋ฌถ์์ struct๋ฅผ ๊ถ์ฅํฉ๋๋ค.
- struct ๊ถ์ฅ: ๋ชจ๋ ๋ฉค๋ฒ๊ฐ ํญ์ ์ ํจํ ์ํ์ผ ๋ (์ขํ, ์์๊ฐ)
- class ๊ถ์ฅ: ๋ฉค๋ฒ ๊ฐ ์์กด์ฑ์ด๋ ์ ํจ์ฑ ์กฐ๊ฑด์ด ์์ ๋
Q5. ์ธ๋ฆฌ์ผ ์์ง์์ USTRUCT์ UCLASS์ ์ฐจ์ด๋?
- USTRUCT: GC ๋ฏธ์ง์, UPROPERTY๋ง ๋ฆฌํ๋ ์ , ๋ธ๋ฃจํ๋ฆฐํธ ์ ํ์ , ๋จ์ผ ์์, ๊ฒฝ๋ ๋ฐ์ดํฐ ์ปจํ ์ด๋ (FVector ๋ฑ)
- UCLASS: UObject GC ๊ด๋ฆฌ, UPROPERTY + UFUNCTION ์ ์ฒด ๋ฆฌํ๋ ์ , ๋ธ๋ฃจํ๋ฆฐํธ ์์ ์ง์, UObject ๊ณ์ธต ์์, ๊ฒ์ ๊ฐ์ฒด (AActor, UComponent)
1
2
3
4
5
6
7
8
9
10
11
12
13
USTRUCT(BlueprintType)
struct FDamageInfo {
GENERATED_BODY()
UPROPERTY() float Damage;
UPROPERTY() AActor* Instigator;
};
UCLASS()
class AMyCharacter : public ACharacter {
GENERATED_BODY()
UFUNCTION(BlueprintCallable)
void TakeDamage(FDamageInfo Info);
};
Q5-1. UCLASS์ ๊ฐ๋น์ง ์ปฌ๋ ํฐ(GC)์ ์ฐ๊ฒฐ
์ธ๋ฆฌ์ผ์ GC๋ C++ ํ์ค GC๊ฐ ์๋๋ผ ์์ง ์์ฒด ๊ตฌํ์ ๋๋ค. UObject๋ฅผ ์์ํ UCLASS๋ง GC ๋์์ด ๋ฉ๋๋ค.
GC ๋์ ์๋ฆฌ (Mark & Sweep):
- Mark โ ๋ฃจํธ ์ค๋ธ์ ํธ์์ ์ถ๋ฐ, UPROPERTY๋ก ์ฐธ์กฐ๋ UObject๋ฅผ ์ฌ๊ท์ ์ผ๋ก ํ์
- Sweep โ ํ์๋์ง ์์ UObject๋ฅผ ํ๊ดด
- ์ฃผ๊ธฐ โ ๊ธฐ๋ณธ 60์ด (
gc.TimeBetweenPurgingPendingKillObjects)
GC Root๊ฐ ๋๋ ๊ฒ๋ค:
AddToRoot()๋ก ์ง์ ๋ฑ๋กํ UObject- ์๋์ ์์๋ AActor
- ๊ธ๋ก๋ฒ UEngine, UGameInstance ๋ฑ ์์ง ์ฑ๊ธํด
- UPROPERTY๋ก ์ฐธ์กฐ๋ ์ฒด์ธ ์ ์ฒด
1
2
3
4
5
6
7
8
9
10
11
UCLASS()
class AMyActor : public AActor {
GENERATED_BODY()
// โ
UPROPERTY โ GC๊ฐ ์ถ์
UPROPERTY()
UMyComponent* SafeComp;
// โ raw ํฌ์ธํฐ โ GC๊ฐ ๋ชจ๋ฆ โ ๋๊ธ๋ง ํฌ์ธํฐ!
UMyComponent* DangerComp;
};
USTRUCT ์์์ UObject ์ฐธ์กฐํ๊ธฐ:
1
2
3
4
5
6
7
8
USTRUCT(BlueprintType)
struct FWeaponData {
GENERATED_BODY()
UPROPERTY()
UStaticMesh* WeaponMesh; // USTRUCT ์์ฒด๋ GC ๋์ ์๋์ง๋ง
UPROPERTY() // ์์ UPROPERTY๋ GC๊ฐ ์ถ์
float Damage;
};
Q6. struct์ ํฌ๊ธฐ์ ๋ฉ๋ชจ๋ฆฌ ์ ๋ ฌ (padding & alignment)
์ปดํ์ผ๋ฌ๋ CPU์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจ์จ์ ์ํด ํจ๋ฉ ๋ฐ์ดํธ๋ฅผ ์ฝ์ ํฉ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// ๋นํจ์จ์ ๋ฐฐ์น โ 12๋ฐ์ดํธ
struct Bad {
char a; // 1 + 3 padding
int b; // 4
char c; // 1 + 3 padding
};
// ํจ์จ์ ๋ฐฐ์น โ 8๋ฐ์ดํธ
struct Good {
int b; // 4
char a; // 1
char c; // 1 + 2 padding
};
// #pragma pack๋ก ์ ๋ ฌ ์ ์ด
#pragma pack(push, 1)
struct Packed {
char a; // 1
int b; // 4
char c; // 1
}; // sizeof = 6
#pragma pack(pop)
Q7. ๋น struct/class์ ํฌ๊ธฐ๋?
C++ ํ์ค์์ ๋ชจ๋ ๊ฐ์ฒด๋ ๊ณ ์ ํ ์ฃผ์๋ฅผ ๊ฐ์ ธ์ผ ํ๋ฏ๋ก, ๋น struct/class๋ ์ต์ 1๋ฐ์ดํธ์ ๋๋ค.
1
2
3
4
5
6
7
8
struct Empty {};
sizeof(Empty); // 1
// Empty Base Optimization (EBO)
struct Derived : Empty {
int x;
};
sizeof(Derived); // 4
C++20์ [[no_unique_address]] ์์ฑ์ผ๋ก ๋ฉค๋ฒ์๋ EBO์ ๊ฐ์ ์ต์ ํ ๊ฐ๋ฅ.