从StructArray Ue4中删除

时间:2017-05-23 13:27:00

标签: c++ arrays unreal-engine4

我从我的TArray of structs中删除struct有点挣扎。我的struct包含AudioComponent和float.I正在使用Array.RemoveAt(index),但我从中得到的只是删除了我的一半结构,即AudioComponent 。 这是为什么?我的功能删除元素如下所示:

void RemoveArrayElement( UAudioComponent AudioComponent )
{
    for( int i=0; i<Array.Num(); i++ )
    {
        if( AudioComponent == Array[i].AudioComponent )
        {
            Array.RemoveAt( i );
        }
    }
}

我想要实现的是完全删除索引,AudioComponent,它的浮动。

2 个答案:

答案 0 :(得分:0)

首先请记住,比较两个对象并不一定会导致预期的平等结果。使用==运算符意味着执行一个指定应该发生什么的函数(bool operator==(L, R);)。因此,如果你没有重载==运算符,那么除非你查看它所定义的源代码,否则你不知道使用它会导致什么。由于您要删除确切的音频组件而不是看起来相同的实例,因此您希望在数组中使用指针。这也有助于提高性能,因为在调用RemoveArrayElement(...);而不是单个指针时,您不会复制整个组件。此外,当阵列中存在两个相同的音频组件且它们位于索引a和a + 1时,则在下一次迭代时删除索引a处的音频组件将跳过第二个音频组件,因为所有上层索引都减1。 / p>

答案 1 :(得分:0)

您的代码存在一些问题。正如其他人在评论中提到的那样,你应该使用指针。如果我没弄错的话,你不能使用这样的结构:

UPROPERTY()
    TArray<UAudioComponent> invalidArray;

您应该使用UPROPERTY宏,否则您的属性可能会被垃圾收集。 UPROPERTY wiki

接下来就是你正在改变你正在迭代的数组。我写了几个方法,让我们来看看它们:

void RemoveArrayElement(UAudioComponent* AudioComponent)
{
    TArray<UAudioComponent*> audioArray; // array will be initialized somewhere else, this is for demo purpose.


    // you always should check your pointers for validity
    if (!AudioComponent || !AudioComponent->IsValidLowLevel() || AudioComponent->IsPendingKill())
        return;


    // Correct approach 1 (multiple):
    TQueue<UAudioComponent*> toDelete;

    for (int i = 0; i < audioArray.Num(); i++)
    {
        auto item = audioArray[i];
        if (AudioComponent == item || true) // we simulate another condition for multiselect
        {
            toDelete.Enqueue(item);
        }
    }

    // better approach for iteration:
    for (auto item : audioArray)
        if (item == AudioComponent || true) // we simulate another condition for multiselect
            toDelete.Enqueue(item);


    // finalize deletion in approach 1
    UAudioComponent* deleteItem;
    while (toDelete.Dequeue(deleteItem))
        audioArray.Remove(deleteItem);




    // almost correct approach 2 (single) :
    UAudioComponent* foundItem;

    for (auto item : audioArray)
        if (item == AudioComponent)
        {
            foundItem = item;
            break;          // we can skip rest - but we must be sure, that items were added to collection using AddUnique(...)
        }

    if (foundItem)
        audioArray.Remove(foundItem);


    // correct and the best - approach 3 (single)

    audioArray.Remove(AudioComponent);
}