Unreal structs initialization

Hi! After hard debuging I’ve realized I don’t understand how struct inititalization works in UE. Could someone please explain me what’s going on here. For example I have a struct:

struct FCharacterAttributes : public FTableRowBase {
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, SaveGame)
	USkeletalMesh* Hair;
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	int32 Speed;
}

When I create that struct object as “FCharacterAttributes attr;” I expect Hair will be nullptr and Speed = 0;

But if I debug this object after creation it will contain Hair => {Incorrect pointer here}, Speed => 2132045616. After that GC tries to delete {Incorrect pointer here} and I have exception “Invalid object in GC”. If I manualy clear Head = nullptr, it works. I had this issue yesterday, but now I can not reproduce it o_O

So what’s wrong with it? Why sometimes pointer initialized as non nullptr and why int value is not 0? How to avoid this situation?
Thanks!

1 Like

You need to create constructors for the struct as if it was a class and you can fix this.

struct FCharacterAttributes : public FTableRowBase {

	GENERATED_BODY()
// inserted lines
public:   
    FCharacterAttributes( ) { Hair = nullptr; Speed = 0; }
// end of inserted lines

	UPROPERTY(EditAnywhere, BlueprintReadWrite, SaveGame)
	USkeletalMesh* Hair;
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	int32 Speed;
}

Note that you can also have more than one constructor.

2 Likes

Unreal doesn’t do anything special in regards to structure initialization. It’s all just standard C++, so what you’re getting is the random stack data in the memory where your structure was allocated.

In addition to @NilsonLima’s suggestion to create constructors, you can also use inline initializers like this:

struct FCharacterAttributes : public FTableRowBase {
	GENERATED_BODY()

	UPROPERTY(EditAnywhere, BlueprintReadWrite, SaveGame)
	USkeletalMesh* Hair = nullptr;
	
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	int32 Speed = 0;
}

Another wrinkle is that Unreal does require that USTRUCTs have a default constructor. So if you add a constructor with any non-defaulted parameters, you’ll also have to make sure to have one that is callable without any parameters.

But you can simplify that a little with a defaulted constructor like so:
FCharacterAttributes( ) = default;
if you’ve used the inline initializers.

You can also use inline initializers for properties of UCLASS’s, but in that case Unreal does initialize everything to zero so you can omit those defaults if you want (I don’t recommend it, but you can).

3 Likes

Thx for answers, but why structs require initializators (in case of pointers at least), but classes not? Do classes have default initializators?

Does FCharacterAttributes( ) = default; mean FCharacterAttributes( ) : Hair (nullptr), Speed (0) ?

How can I initialize TSubclassOf to prevent unexpected behaviour?

I’ve tried this way USkeletalMesh* Hair = nullptr; (maybe I had cached class somewhere), but I had same issue as without default value, so Hair contained incorrect object inside.

Is there imprtant difference bewtween dafault values and inline initializators?

Why core UE structs doesn’t have initilizators and is there a rule when to use them?

/** Default constructor (no initialization). */
	FORCEINLINE FVector();

I’ve found additional way to initialize by default values

struct foo {
    bool a {};
    bool b {};
    bool c {};
 } bar;

Is there any disadvantage to use it? Will it correctly initialize TArray smths {} ?

Thx

Because the object framework requires you to go through one of Unreal’s API’s to allocate it. Either SpawnActor, NewObject, CreateWidget, etc are required to be called which allow Unreal to add a step where they initialize the properties to something known (ie 0). They can’t do that for structures because they have no way to hook into the creation of one when you’re instancing them (probably for the best too).

It does if those are the values you’ve specified for the inline initializers. If a member is itself a structure (like FVector) it will use the default constructor if you don’t have an initializer specified.

That’s probably the case, it should definitely work.

Inline initializers are just one way to do default values. Specifying a constructor to assign default values is another, perfectly reasonable way to do it). The inline ones are restricted to values known at compile time, so if you want to construct it with a runtime value you’d have to use a constructor with parameters.

Don’t know. Much of the engine probably predates the C++ language support for that form of initializer. There’s no specific rules. I usually default to using them unless there’s a specific reason not to.

Yes, there are lots of ways to initialize variables. But none of it has anything to do with Unreal. You might want to do a review of basic C++ principles or ask questions in a C++ community instead.

The main disadvantage is that it’s a bit unreadable. You have to know that it’s going to set it to 0. bool a = false; is much more maintainable. Using { } can correctly initialize a TArray, but in that case you shouldn’t need to do anything since the default constructor for TArray would be used and initialize it to that anyway. You only need to specify initializers for built in types (this includes any type of raw pointer) or structure types where you want to init it to something other than it’s default value. So if you wanted to init your TArray to “1, 2, 3, 4” you could do TArray< int > a = { 1, 2, 3, 4 };.

3 Likes

MagForceSeven The reason why I asked here, sometimes hard to understand where is Unreal C++ feature and pure C++. Mainly I’m Java dev, so it was unexpected that properties may not be initialized . Thanks a lot for very detailed answers!

1 Like

Absolutely! I am not knocking you for asking here at all! I just wanted to point out a spot where there is a ton more information out there (because it’s pure C++) that would likely be a) better than anything I would be able to write up and b) be much more comprehensive than anything I could write up in this forum. Apologies if my wording was poor in that regard.

3 Likes