2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[UE4] メンバ変数の初期化について

Last updated at Posted at 2021-08-03

#【概要】
「UE4では明示的な初期化をしなくても、メンバ変数はに0に初期化されるもの」
勝手にそう思い込んでいたが、実際そんなことはなく、理解が浅いまま危ない実装をしていたので、これを期にメンバ変数の初期化についてまとめてみた。

動作環境はUE4.24、VisualStudio 2019を使用。

#【公式ドキュメントを読んでみる】
まずは公式ドキュメントを読んでみる。
https://docs.unrealengine.com/4.26/ja/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/Objects/Optimizations/

#####プロパティの自動初期化
コンストラクタが呼び出される前に、UObjects は初期化時に自動的にゼロになります。これはクラス全体、UProperties、ネイティブ メンバでも同様に起こります。

つまり、UObjectを継承したクラスのメンバ変数は、明示的に初期化をしていなくても、0に初期化されるということが分かった。

逆に言えば、UObjectを継承していないクラスや、構造体などのメンバ変数は、自動的に初期化されないことになる。

#【実践】
上記を踏まえた上で、実際にコードを書いてみる。

Test.h
//UObjectを継承しないクラス
class Test
{
public:
	Test(){};

	bool BoolVal;
	int32 IntVal;
	float FloatVal;
	class AActor* Ptr;
};

//UObjectを継承したクラス
UCLASS()
class UTest_UObject : public UObject
{
	GENERATED_BODY()

public:
	UTest_UObject(){};

	bool BoolVal;
	int32 IntVal;
	float FloatVal;
	class AActor* Ptr;
};
Player.cpp
APlayer::BeginPlay()
{
	//適当な場所でインスタンス生成
	Test* TestPtr = new Test();
	UTest_UObject* TestPtr_UObject = NewObject<UTest_UObject>(this, UTest_UObject::StaticClass());

	UE_LOG(LogTemp, Log, TEXT("TestPtr BoolVal:%d, IntVal:%d, FloatVal:%.2f, Ptr:%d"), (int32)TestPtr->BoolVal, TestPtr->IntVal, TestPtr->FloatVal, TestPtr->Ptr);
	UE_LOG(LogTemp, Log, TEXT("TestPtr_UObject BoolVal:%d, IntVal:%d, FloatVal:%.2f, Ptr:%d"), (int32)TestPtr_UObject->BoolVal, TestPtr_UObject->IntVal, TestPtr_UObject->FloatVal, TestPtr_UObject->Ptr);
}

実行結果

LogTemp: TestPtr BoolVal:96, IntVal:342, FloatVal:0.00, Ptr:6619236
LogTemp: TestPtr_UObject BoolVal:0, IntVal:0, FloatVal:0.00, Ptr:0

ドキュメント通り、UObjectを継承したクラスは全てのメンバ変数が0に初期化されたが、継承していないクラスは初期化されなかった。

#【初期化の方法】
明示的に初期化する方法はいくつかあるので、軽く触れておく。

Test.h
class Test
{
public:
	Test();
	//一番最初に初期化される
	int32 IntVal = 1;
};
Test.cpp
Test::Test()
	//初期化リスト。ヘッダーの次に初期化される。
	:IntVal(2)
{
	//初期化リストの次に初期化される。代入と同じなので負荷は他に比べて重い。
	IntVal = 3;
}

#【結論】
初期化されなかった場合、元々メモリに存在していた値がその変数の値になる。
ローカル変数はメモリの書き換えが多いスタック領域に作られる為、初期化しないとゴミが入ることが多く、コンパイラによっては初期化しないとエラーになる場合がある。
ただし、ヒープ領域に作られるから大丈夫というわけではないので、明示的に初期化する習慣を付けることをオススメする。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?