bool - boolean 값(bool 크기 추정 금지). BOOL 은 컴파일되지 않습니다.
TCHAR - character(TCHAR 크기 추정 금지)
uint8 - unsigned byte(1 바이트)
int8 - signed byte (1 바이트)
uint16 - unsigned "short"(2 바이트)
int16 - signed "short"(2 바이트)
uint32 - unsigned int(4 바이트)
int32 - signed int(4 바이트)
uint64 - unsigned "quad word"(8 바이트)
int64 - signed "quad word"(8 바이트)
float - single precision floating point(4 바이트)
double - double precision floating point(8 바이트)
PTRINT - 포인터를 가질 수 있는 integer(PTRINT 크기 추정 금지)
int
가 아닌 int숫자
를 사용한다.char
이 아닌 TCHAR
을 사용한다.// Bad:
t = s + l - b;
// Good:
TotalLeaves = SmallLeaves + LargeLeaves - SmallAndLargeLeaves;
- 도움이 되는 코멘트를 작성하라
```cpp
// Bad:
// Leaves 증가
++Leaves;
// Good:
// 찻잎이 더 있다는 것을 알았습니다.
++Leaves;
// Bad:
// 잎의 총개수는
// 작은 잎과 큰 잎을 더한 것에서
// 둘 다인 것을 뺀 것입니다.
t = s + l - b;
// Good:
TotalLeaves = SmallLeaves + LargeLeaves - SmallAndLargeLeaves;
// Bad:
// Leaves 절대 증가 아님!
++Leaves;
// Good:
// 찻잎이 더 있다는 것을 알았습니다.
++Leaves;
void SomeMutatingOperation(FThing& OutResult, const TArray<Int32>& InArray)
{
// InArray는 SomeMutatingOperation에 의해 수정되지 않지만, OutResult는 수정될 수도 있습니다.
}
void FThing::SomeNonMutatingOperation() const
{
// 이 코드는 자신을 부른 FThing을 수정하지 않습니다.
}
TArray<FString> StringArray;
for (const FString& : StringArray)
{
// 이 루프의 바디는 StringArray를 수정하지 않습니다.
}
// 포인터 연산자에 대해 증감 연산이 불가.
// 가리키는 데이터는 const가 아니기 때문에 가리키는 데이터 자제는 변경 가능.
T* const Ptr = ...;
// 레퍼런스 자체에 const라는 의미가 내포되어 있다.
T& const Ref = ...;
// 나쁨 - const 배열 반환
// 복사가 일어난다.
const TArray<FString> GetSomeArray();
// 좋음 - const 배열로의 레퍼런스 반환
// 복사가 일어나지 않는다.
// TArray에 있는 데이터를 고칠 수 없다.
const TArray<FString>& GetSomeArray();
// 좋음 - const 배열로의 포인터 반환
// 증감연산 가능
// 포인터가 가리키는 데이터는 수정 불가
const TArray<FString>* GetSomeArray();
// 나쁨 - const 배열로의 const 포인터 반환
// 포인터 수정 불가
// 포인터가 가리키는 데이터 수정 불가
const TArray<FString>* const GetSomeArray();
NULL
보다는 nullptr
을 사용해야 한다.for
보다 새 스타일의 for
를 사용한다.TMap<FString, int32> MyMap;
// 옛 스타일
for (auto It = MyMap.CreateIterator(); It; ++It)
{
UE_LOG(LogCategory, Log, TEXT("Key: %s, Value: %d"), It.Key(), *It.Value());
}
// 새 스타일
for (TPair<FString, int32>& Kvp : MyMap)
{
UE_LOG(LogCategory, Log, TEXT("Key: %s, Value: %d"), *Kvp.Key, Kvp.Value);
}
// 옛 enum
UENUM()
namespace EThing
{
enum Type
{
Thing1,
Thing2
};
}
// 새 enum
UENUM()
enum class EThing : uint8
{
Thing1,
Thing2
}
std::move
대신 MoveTemp
를 사용한다.if (bThing)
{
return;
}
switch case
문에서는 break
, return
, continue
, fall through 코멘트 등을 활용하여switch (condition)
{
case 1:
...
// falls through
case 2:
...
break;
case 3:
...
return;
case 4:
case 5:
...
break;
default:
break;
}
#pragema once
를 반드시 작성한다.private
로 선언하고 getter와 setter로 접근한다.final
을 사용한다.TEXT()
매크로를 사용한다.// Bad:
if ((Blah->BlahP->WindowExists->Etc && Stuff) &&
!(bPlayerExists && bGameStarted && bPlayerStillHasPawn &&
IsTuesday())))
{
DoSomething();
}
// Good:
const bool bIsLegalWindow = Blah->BlahP->WindowExists->Etc && Stuff;
const bool bIsPlayerDead = bPlayerExists && bGameStarted && bPlayerStillHasPawn && IsTuesday();
if (bIsLegalWindow && !bIsPlayerDead)
{
DoSomething();
}
// Good:
FShaderType* Ptr
// Bad:
FShaderType *Ptr
FShaderType * Ptr
static
변수를 선언하게 되면 그 헤더를 참조하는 모둔 인스턴스에// Bad:
// SomeModule.h
static const FString GUsefulNamedString = TEXT("String");
// Good:
// SomeModule.h
extern SOMEMODULE_API const FString GUsefulNamedString;
// SomeModule.cpp
const FString GUsefulNamedString = TEXT("String");
bool
함수 파라미터는 사용을 피하고 enum
을 사용한다.// 옛 스타일
FCup* MakeCupOfTea(FTea* Tea, bool bAddSugar = false, bool bAddMilk = false, bool bAddHoney = false, bool bAddLemon = false);
FCup* Cup = MakeCupOfTea(Tea, false, true, true);
// 새 스타일
enum class ETeaFlags
{
None,
Milk = 0x01,
Sugar = 0x02,
Honey = 0x04,
Lemon = 0x08
};
ENUM_CLASS_FLAGS(ETeaFlags)
FCup* MakeCupOfTea(FTea* Tea, ETeaFlags Flags = ETeaFlags::None);
FCup* Cup = MakeCupOfTea(Tea, ETeaFlags::Milk | ETeaFlags::Honey);
virtual
및 override
키워드를 사용한다.