Hi everyone,
This one seems to be trivial but I do not know how it should be done. Basically I want to create an array of actors and operate on it. I can create an array and add actors to it but I cannot understand how to include the array in a foreach loop.
I seriously doubt there’s any measurable difference in performance between the two versions. More likely they compile to the same exact machine code. Give the compiler some credit.
Well, it is not for-each, it is for. Still, there are three problems:
It is bad idea to use Array.Num() inside of for statement.
There is no sense in using i++ instead of ++i.
You don’t usually need int as it is too huge for not-BigData (and can differ in size from one C++ standard to another).
In terms of performance, it is better to write in other way, so that your code won’t run in too different time on different compilers:
/* If you do care about order... */
uint8 Len = Array.Num();
for (uint8 i = 0; i < Len; ++i)
{
Array[i].DoStuff();
}
/* And if you don't... */
for (int8 i = Array.Num() - 1; i >= 0; --i)
{
Array[i].DoStuff();
}
Update: one more variation…
for (uint8 i = Array.Num() - 1; i-- ; )
{
Array[i].DoStuff(); // However, it won't reach 0-th element...
// Array[i - 1] can work if we start from Array.Num() element, but it's +1 operation on each iteration...
}
It’s not necessarily a bad idea to use Array.Num() inside the loop signature. As RotemS pointed out, if the length of the array doesn’t change based on the code inside the loop body then the compiler will VERY likely optimize the call to Num() out of existence. I agree that relying on compilers too much for optimization is not a good thing, but to simply state that it should never be done without qualifying that in any way isn’t something I can agree to.
For the same reason as #1 and because there is no additional logic to occur anyway (in this example), there is actually no sense in using ++i over i++ (or vice-versa). I don’t even see a semantic difference in using either since it should be clear to the reader that nothing is going to happen to i either before or after it is assigned.
Are you targeting 8-bit processors or extremely memory deprived systems? Why use int8? More than likely, if you are using UE4, you are targeting 32-bit or 64-bit processors, which have 32/64-bit registers. Unless the compiler saves you, using smaller sized types may actually result in poorer performance (though you’ll save on memory, but for cases like indexers for loops don’t bother with int8 or using an unsigned integer just because logically it shouldn’t go negative).
If in the loop body you plan on using the variable “i” to access a specific element in the array and the length of the array won’t change inside the loop body, then performance-wise the best approach is to use a for each loop like Steve suggested.
I’m not going to comment on the “optimal” way to iterate through TArrays, but the following is how they are iterated in the engine code, so I assume this method is at least safe.
TArray<ExampleClass> MyArray;
// Some code which assigns value to the array...
// Iterate through the array
MyArray.Reserve(MyArray.Num());
for (int i = 0; i < MyArray.Num(); ++i)
{
// Extract item from the array
ExampleClass MyItem = MyArray[i];
}
Source: UE 4.20.1 - Engine/Source/Runtime/Engine/Private/Actor.cpp Line 2699
“…which is executed after every iteration of the loop and before re-evaluating condition. Typically, this is the expression that increments the loop counter”
for : is the for each statement in C++. Just because theres no foreach keyword doesnt mean it isnt the same thing.
No, its not. If the array isnt being mutated then its fine, and if it is, then i cache the array first.
Its literally a stylstics choice. No one in the history of ever has had worse preforming code because they put the plus signs in the wrong order. Its a complete over reaction, and any code compiler could refactor i++ into ++i if it can. This is micro optimizing.
I prefer i++ because it makes more semantic sense to me. Theres i = i + 1, i += , i.Add(1) so naturally i++ is more constistent to have the identifier first, then the operation afterwards. Preformance wise it will almost never make a difference, and if it does, then that’s the fault of the implimenter of the ++ operator.
What? Are you in the 70s? Computers can handle using even 1000s of ints that arent needed, this is abusrd. In C#, for example, an int is actually faster than a byte or short, because the compilers were designed more efficently to use ints, because they were more common, so it might actually be better to use int.
Do you have any measurements for any of this? This is such a micro optimization that literally doesn’t matter. You’re talking about the preformance of a for loop