Modifying one array causes the other array to be modified

I use this blueprint function to fetch all the loot for player, where the function “Filter” is used to query the loot from the enemy, then iterate over them and retrieve them. The number of elements in the array returned by the filter function has changed after the elements have been removed from lootInventory, the array returned by the filter function is a copied array, in theory it should not be affected.

Here is some C++ code

TArray<UInventoryItemInstance*> UInventory::filter(EInventoryItemPrimaryType type) const
{
	TArray<UInventoryItemInstance*> ret;
	if (type == EInventoryItemPrimaryType::Unknown)
	{
		for (UInventoryItemInstance* it : this->_items)
			ret.Add(it);
	}
	else
	{
		for (UInventoryItemInstance* it : this->_items)
		{
			if (it->getItem()->getPrimaryType() == type)
				ret.Add(it);
		}
	}

	return ret;
}

UInventoryItemInstance* UInventory::takeoutInstance(UInventoryItemInstance* instance, int num)
{
	if (!instance || num == 0)
		return nullptr;

	if (this->_items.Find(instance) == INDEX_NONE)
		return nullptr;

	if (num >= instance->getNum() || num < 0)
	{
		this->_items.Remove(instance);
		return instance;
	}
	
	auto ret = instance->clone();
	ret->setNum(num);

	instance->setNum(instance->getNum() - num);
	if (instance->getNum() == 0)
	{
		this->_items.Remove(instance);
	}

	return ret;
}

Update:
When I removed the “const” modifier from the “Filter” function, the problem went away. It looks like Unreal is doing something wrong with “const”.

This has to do with how Pure nodes behave vs. non-pure.

Here are a couple posts describing basically the same issue you are experiencing :

On C++ side you normally make pure functions with the BlueprintPure specifier. I’m not aware of the engine doing that automatically for const methods, but maybe that is the case. Did your Filter node become different after removing const (added exec pins) ?

When const is removed, the data returned by the Filter function is the same as before, but it is no longer changed by the change in the other array.
Note that the array returned by the filter function is a copied array, which should not be size modified under any circumstances, even if GC occurred and UInventoryItemInstance be destroyed(There is definitely no GC happening during the for loop of above blueprint function).

The array copy itself is not really modified, but the filter node is entirely re-evaluated, so it re-filters the contents of LootInventory, which has been modified, and returns the new result.

Add logging in your CPP filter function and you’ll observe how many times it is being executed.

I see. Thank you very much