C++ 从结构数组Ue4中删除

C++ 从结构数组Ue4中删除,c++,arrays,unreal-engine4,C++,Arrays,Unreal Engine4,我在从结构的TArray中删除结构时遇到了一些困难。我的结构包含AudioComponent和float。我使用的是Array.RemoveAt(index),但我从中得到的只是删除了结构的一半,即AudioComponent。 为什么呢?我的删除元素的函数如下所示: void RemoveArrayElement( UAudioComponent AudioComponent ) { for( int i=0; i<Array.Num(); i++ ) {

我在从结构的TArray中删除结构时遇到了一些困难。我的结构包含AudioComponent和float。我使用的是Array.RemoveAt(index),但我从中得到的只是删除了结构的一半,即AudioComponent。 为什么呢?我的删除元素的函数如下所示:

void RemoveArrayElement( UAudioComponent AudioComponent )
{
    for( int i=0; i<Array.Num(); i++ )
    {
        if( AudioComponent == Array[i].AudioComponent )
        {
            Array.RemoveAt( i );
        }
    }
}
UPROPERTY()
    TArray<UAudioComponent> invalidArray;
void removeraryElement(UAAudioComponent AudioComponent)
{

对于(int i=0;i首先请记住,比较两个对象并不一定会得到预期的相等结果。使用==运算符意味着执行一个函数(
bool运算符==(L,R);
)这指定了应该发生的情况。因此,如果没有重载==运算符,则除非查看定义它的源代码,否则您不知道使用它会产生什么结果。因为您希望删除确切的音频组件,而不是其外观相同的实例,所以您希望在数组中使用指针。这也有助于提高性能由于在调用
RemoveArrayElement(…)时没有复制整个组件;
但只有一个指针。另外,当数组中存储了两个相同的音频组件,它们位于索引a和a+1处时,在下一次迭代中删除索引a处的音频组件将跳过第二个音频组件,因为所有较高的索引都递减了一个。

您的代码几乎没有问题。正如其他人提到的那样在注释中,您应该使用指针。如果我没有弄错的话,您不允许使用这样的构造:

void RemoveArrayElement( UAudioComponent AudioComponent )
{
    for( int i=0; i<Array.Num(); i++ )
    {
        if( AudioComponent == Array[i].AudioComponent )
        {
            Array.RemoveAt( i );
        }
    }
}
UPROPERTY()
    TArray<UAudioComponent> invalidArray;
upperty()
柏油虫病;
您应该使用UPROPERTY宏,否则您的属性可能会被垃圾收集

下一件事是您正在更改迭代的数组。我写了几个方法,让我们看看它们:

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);
}
void removeraryElement(UAAudioComponent*AudioComponent)
{
TArray audioArray;//数组将在其他地方初始化,这是为了演示。
//你应该经常检查指针的有效性
如果(!AudioComponent | |!AudioComponent->IsValidLowLevel()| | AudioComponent->IsPendingKill())
返回;
//正确的方法1(多个):
托德莱特;
对于(int i=0;i
你说的“删除我的结构的一半”是什么意思?我不明白你如何删除结构的一半,或者这是如何表现出来的(或者你是如何看待它的),比如说数组[0]=Stuct(AudioComponent0,float0)。在我使用Array.RemoveAt(0)之后,我得到的是数组[0]=Stuct(某个无效值,float0)。因此,数组的大小不会更改,并且
数组中的剩余元素不会向前“移动”?您不应该按值存储或复制UObject。而是使用指针(`UAudioComponent*)和UpProperty以防止它们被垃圾收集器破坏。阅读更多:看起来元素本身仍然存在,因为结构的一个参数仍然有效且可访问,即使不再有AudioComponent。在我引用您的wiki链接后,您的数组不会更改其大小:“GC系统不会对非UPROPERTY变量进行计数。”。因此,如果不是UPROPERTY,则不会对任何内容进行垃圾收集。