Custom (Template) Container and Pointers

Hello!

I am experiencing some odd behavior with a custom template container class. What is happening is I fill this container with pointers to a class that inherits from AActor after I spawn them in the world like so

	for (int32 x = -Size.X; x <= Size.X; x++) {
		for (int32 y = -Size.Y; y <= Size.Y; y++) {
			for (int32 z = -Size.Z; z <= Size.Z; z++) {
				AMyClass *NewMyClass = (AMyClass*) GetWorld()->SpawnActor(MyClass::StaticClass());
				NewMyClass->SetActorLocation(FVector(x, y, z)); 
				Grid.Add(NewMyClass, x, y, z);
			}
		}
	}

Then later on I attempt to call methods from MyClass.

	for (int32 x = Grid.GetMinX(); x <= Grid.GetMaxX(); x++) {
		for (int32 y = Grid.GetMinY(); y <= Grid.GetMaxY(); y++) {
			for (int32 z = Grid.GetMinZ(); z <= Grid.GetMaxZ(); z++) {
				AMyClass *Class = Grid.Get(x, y, z);
				if (!Class) { continue; } // If nothing here, skip it

				if (Class->IsDirty()) {
					Class->DoStuff();
				}
			}
		}
	}

But it seems when I call Grid.Get(…) I always retrieve a default version (without any properties initialized). I am still learning all the ins and outs of UE4 C++, but could this have something to do with UE4 garbage collector?

The header for my Grid class is as follows

#pragma once
#include <vector>

template <typename T>
class MYPROJECT_API TGrid
{

public:
	TGrid<T>::TGrid() :
		MinX(0),
		MinY(0),
		MinZ(0),
		MaxX(0),
		MaxY(0),
		MaxZ(0),
		SizeX(0),
		SizeY(0),
		SizeZ(0)
	{}
	TGrid<T>::~TGrid() {}

	// The following 6 methods return the min or max values of the grid
	int32 GetMinX() { return MinX; }
	int32 GetMinY() { return MinY; }
	int32 GetMinZ() { return MinZ; }
	int32 GetMaxX() { return MaxX - 1; }
	int32 GetMaxY() { return MaxY - 1; }
	int32 GetMaxZ() { return MaxZ - 1; }

	// Get the object at current valid location
	T Get(const int32 &x, const int32 &y, const int32 &z);

	// Add or replace at given grid coordinates (expand grid if necessary)
	void Add(T obj, const int32 &x, const int32 &y, const int32 &z);

private:
	std::vector<std::vector<std::vector<T>>> Grid; // Pointer to 3D array of type T
	int32 MinX, MinY, MinZ, MaxX, MaxY, MaxZ; // Virtual array size
	int32 SizeX, SizeY, SizeZ; // Actual size

	// Check to make sure grid[x,y,z] is valid
	bool IsCorrectIndex(const int32 &x, const int32 &y, const int32 &z);

	// Set the object at current valid location
	void Set(T obj, const int32 &x, const int32 &y, const int32 &z);

	// Expand the grid size
	void ExpandGrid(const int32 &dMinX, const int32 &dMinY, 
					const int32 &dMinZ, const int32 &dMaxX, 
					const int32 &dMaxY, const int32 &dMaxZ);
};

What does the constructor of MyClass look like?

AMyClass::AMyClass(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP),
bIsDirty(false)
{
// Create a mesh with name
Mesh = PCIP.CreateDefaultSubobject(this, TEXT(“MyClassMesh”));
RootComponent = Mesh; // Set mesh as root component

	//Mobility
	Mesh->SetMobility(EComponentMobility::Stationary);
	//Component Setup
	Mesh->CastShadow = true;
	Mesh->bCastDynamicShadow = true;
	Mesh->BodyInstance.SetObjectType(ECC_WorldDynamic);
	Mesh->BodyInstance.SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);

	// Set material
	static ConstructorHelpers::FObjectFinder<UMaterial> Mat(TEXT("Material'/Game/StarterContent/Materials/M_Ground_Grass.M_Ground_Grass'"));
	if (Mat.Object != NULL) {
		UMaterial *Material = (UMaterial*)Mat.Object;
		UMaterialInstanceDynamic *Material_dyn = UMaterialInstanceDynamic::Create(Material, this);
		Mesh->SetMaterial(0, Material_dyn);
	}
}

That is the constructor for MyClass.

It might be that the code you have included has been quickly modified for this post, but you are in some instances referring to AMyClass and sometimes MyClass. So you’re filling the container with AMyClass pointers, but you’re retrieving MyClass pointers. Can you confirm what type your TGrid is taking?

Sorry, slightly modified yes. AMyClass is correct. As for Grid, is it a part of another class as a static member like so

static TGrid<AMyClass*> Grid;

I notice that TGrid::Add(…) is commented saying that it can add or replace elements of the grid. Have you verified that your code is correctly adding each of the elements to a unique location?
If so, what happens if you try to immediately access the elements of the grid after you store them? Do you still get default objects returned?

Could you also link the instance of TGrid in your code, where do you declare it and how. If it is not templatized on declaration that might cause some construction issues.

My bad you already linked it. I don’t have any ideas why it is doing that, but try replacing vector with ue4’s TArray.