从 StructArray Ue4 移除At
RemoveAt from StructArray Ue4
我很难从我的 TArray 中删除包含 AudioComponent 的 structs.My 结构并且 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 及其浮点数。
首先请记住,比较两个对象并不一定会导致预期的相等结果。使用 == 运算符意味着执行指定应该发生什么的函数 (bool operator==(L, R);
)。因此,如果您没有重载 == 运算符,那么除非您查看定义它的源代码,否则您不知道使用它会产生什么结果。由于您想删除确切的音频组件而不是它看起来相同的实例,因此您希望在数组中使用指针。这也有助于提高性能,因为您在调用 RemoveArrayElement(...);
时不会复制整个组件,而是复制单个指针。此外,当数组中存储了两个相同的音频组件并且它们位于索引 a 和 a+1 时,然后在下一次迭代中删除索引 a 处的音频组件将跳过您的第二个音频组件,因为所有上部索引都递减了一个。
您的代码几乎没有问题。正如评论中提到的其他人一样,您应该使用指针。如果我没记错的话,你不能使用这样的结构:
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);
}
我很难从我的 TArray 中删除包含 AudioComponent 的 structs.My 结构并且 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 及其浮点数。
首先请记住,比较两个对象并不一定会导致预期的相等结果。使用 == 运算符意味着执行指定应该发生什么的函数 (bool operator==(L, R);
)。因此,如果您没有重载 == 运算符,那么除非您查看定义它的源代码,否则您不知道使用它会产生什么结果。由于您想删除确切的音频组件而不是它看起来相同的实例,因此您希望在数组中使用指针。这也有助于提高性能,因为您在调用 RemoveArrayElement(...);
时不会复制整个组件,而是复制单个指针。此外,当数组中存储了两个相同的音频组件并且它们位于索引 a 和 a+1 时,然后在下一次迭代中删除索引 a 处的音频组件将跳过您的第二个音频组件,因为所有上部索引都递减了一个。
您的代码几乎没有问题。正如评论中提到的其他人一样,您应该使用指针。如果我没记错的话,你不能使用这样的结构:
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);
}