📝

[UE5 C++] UPROPERTYとGCについて整理

に公開
4

Discussion

ツバサムスツバサムス

コメント失礼します!
記事の内容とても分かりやすく、勉強になります!
USTRUCT() に関しては

構造体は UObject エコシステムの一部ではないため、UClasses 内で使用することはできません。

とありますが、これは以下のコードのようにクラス内に入れ子で定義した構造体に対して USTRUCT を使用する事は出来ないという意味ではないでしょうか?
この入れ子に対してリフレクションが正常に機能するかはフォーラムの「Class inside Class」という投稿で議論されているのを見つけました!

UCLASS()
class USampleObject : public UObject
{
	GENERATED_BODY()

	USTRUCT()
	struct FSampleStruct
	{
		GENERATED_BODY()
	};
};
NerNer

ありがとうございます!

使用とは何を指しているのでしょうか。普通に UCLASS の中でメンバにできるはずです。何かリフレクションシステムでの制約があるという意味でしょうか? 定義は UCLASS 内では宣言できないのでそのことでしょうか? これもドキュメントからもう読み取れることはないので謎のままとします。

と記事の方で書いておりますが、私もそうではないかなと思っております。
ただ、ドキュメントの意味合いを読み解けず自信がない...という感じです!
そういう解釈をしてる方が他にもいるということで助かります!

フォーラムの内容については「リフレクションシステム都合でクラスは入れ子にできない」ということに関する内容かと思うので、今回の疑問の裏付けとはまた少し違いそうです。


ただ、改めて読み直してみると、

定義は UCLASS 内では宣言できないのでそのことでしょうか?

と思ったものの、 UStruct に限らず UClass も入れ子にはできないはずなので、 UStruct の特徴として言及してるのもおかしい気もしてきました。

Unreal Engine's reflection system recognizes structs as a UStruct, but they are not part of the UObject ecosystem, and cannot be used inside of UClasses.

とあり、もしかしたらリフレクションシステムには認識されるものの「UObjectエコシステムではない」のでUClassとしては扱えない的なことを言いたいのかなという気もしてきました。
(これも自信はないのですが...)

ツバサムスツバサムス

また、UObject のダングリングポインタに関しては一応、UObjectBase::IsValidLowLevel() で確認できますが、同じアドレスに別の UObject が格納されたりした場合は正常に判断できない可能性があるそうです。
UObjectの動作原理」の 35 ページです!

NerNer

ありがとうございます!

HEXA DRIVEさんの資料も読ませてもらっているのですが、お恥ずかしながら IsValidLowLevel() の用途をしっかりと理解できておらず...。

ダングリングポインタが発生するという事態は、UPROPERTY() で保持する人がいなくなり、GC回収されてしまう場合かと思います。

つまり、そのUObjectを生成した所有クラス以外がUPROPERTY()で持たず生ポインタを持っている状態であり、それは本来 TWeakObjectPtr で弱参照すべきで、そうしないからダングリングポインタが検知できないのかなと思っています。

また、コンポーネントなどの場合は明示破棄ができ、この時はpending kill状態になり一時的に不正なUObjectをもらってしまいそうなので IsValid() でチェックしたりするかと思います。ただそれもコンポーネントを所持している人が UPROPERTY で保持していればnullptrを入れてくれるのでダングリングポインタ自体は発生しないはずです。

資料にある通りデバッグ用であり、本来のUObjectエコシステムに乗っ取って使っている限りはダングリングポインタは避けられるので、 IsValidLowLevel() を使うケースは少ないのかなと思っています。(私自身、理解が浅いので認識間違えをしてるところがあるかもしれません)

補足情報ありがとうございました!!