Removing code dynamically? - c++

I'm in a for loop in C++ and i want an "if" clause inside of it to disappear in the next iteration (for the sake of performance) after it checks the value as true once. Is that possible in C++ or in any other language?

There is no magic to change to code dynamically. Executing an if clause in a loop is probably not super-expensive if the if condition is cheap to execute.
If the condition is expensive to evaluate, you may want to protect it with an extra boolean variable:
bool mustCheck = true;
size_t const n = ...; // number of iterations
for (size_t i = 0; i < n; ++i) {
if (mustCheck && theExpensiveCheck(...)) {
mustCheck = false; // turn off the check now
....
}
...
}
If the goal is to execute the check on the first iteration only, you could test if the loop index is 0:
for (size_t i = 0; i < n; ++i) {
if (i == 0 && theExpensiveCheck(...)) {
....
}
...
}
Another option that does not have an if inside the loop is to pull out the if completely, and execute it before the loop if the loop has at least one iteration:
size_t const n = ...; // number of iterations
if (n > 0) {
// do check and execute loop body for first item
if (theExpensiveCheck()) {
....
}
}
// start regular loop, starting at index 1
for (size_t i = 1; i < n; ++i) {
// execute loop body for other items
...
}
The modifications above add extra complexity (and thus potential bugs) to your code. I would recommend to not perform any of these modifications if it's unclear whether there actually is a perform problem with the loop or the if condition. Often enough, applying the above modifications will not result in substantial performance gains, but clearly it depends on the if condition.
Compilers nowadays also provide several powerful loop optimization techniques, so you should make sure you're compiling with all these optimizations turned on.

This is not possible in C++. Once it is compiled, that's it. But, you shouldn't worry about checking a value once. The performance impact is insignificant.
I suppose if the value check was pretty involved (ie more than simple checking if it is T or F), you could add some sort of flag to check first and then skip the rest of the check if it is true. This obviously requires its own check/assignment and is most likely not worth doing.

Related

Is the Break keyword the most efficent way to exit a for loop? C/C++

Is break the most efficient way to exit a loop? In the code snippet below, would line A or line B be the more efficient way to exit the loop? Any links to material on how the break instruction works under the hood would be appreciated.
for (int i = 0; i < 10; i++) {
cout << i << endl;
if (i == 3) {
break; // A
i = 15; // B
}
}
I assume the difference is trivial in most situations, and that A is faster because B requires an assignment, an increment, and then a comparison, but I don't actually know how break works and it's better to know than assume. Thanks!
Let's compile the following code and look at the assembly:
#include <stdio.h>
int loop_with_break() {
for (int i = 0; i < 10; i ++) {
puts("Hello, world!");
if (i == 3) {
break;
}
}
}
int loop_with_assignment() {
for (int i = 0; i < 10; i ++) {
puts("Hello, world!");
if (i == 3) {
i = 10;
}
}
}
int main() {
loop_with_break();
loop_with_assignment();
}
As you can see, when you use break, if i == 3, it'll jump straight out of the loop to the end of the function, whereas if you use i = 10, it'll set i to 10, increment it by 1, then do the comparison, which is slower. However, this was compiled with no optimizations. If you use optimizations, they both end up becoming the same thing. However, since break is more readable and these optimizations are not guaranteed, you should use it for breaking out of loops.
The keyword break will just quit the loop without any comparison made in the loop condition. If you use i = 15 syntax, the loop will iterate next time to verify whether the variable i is greater than 10, if so, then quit.
In short words, break will break the loop without thinking anything, whereas i = 15 will lead one more iteration to look if the condition satisfies it.
You're right! Actually break keyword is very faster for breaking loop!
In your example, if you use line A, then as soon as control reaches this statement, it will immediately break the loop.
On the other hand, if you use line B, then first the assignment will be performed and again the control will go to the condition checking and when the condition will get false then it will exit from the loop!
if you choose while loop you can prefer to make condition false in the while loop. But in this case using break make sense.

Change for loop condition with respect to an external flag (cpp)

I have a code block as following, where the inner for loop code remains the same but only the loop condition changes based on the reverseFlag. Is there a better way to code this without having to copy paste the content of the for loop twice ?
bool reverseFlag=false;
if (reverseFlag)
{
for(int i = 1; i < TotalFrames; i++)
{...}
}
else
{
for(int i = TotalFrames-1; i >0; i--)
{...}
}
Yes, you can do it in a single for loop, like this:
int from, to, step;
if (reverseFlag) {
from = TotalFrames-1;
to = -1;
step = -1;
} else {
from = 0;
to = TotalFrames;
step = 1;
}
for (int i = from ; i != to ; i+= step) {
...
}
A single conditional ahead of the loop prepares loop's parameters - i.e. its starting and ending values and the step, and then the loop uses these three values to iterate in the desired direction.
There are several options. You can:
Use two loops but put the loop body in a separate function/object/lambda.. to avoid duplication.
Use an increasing loop and calculate the real index within the loop:
j = reverseFlag ? TotalFrames - i : i;
Pre-calculate the loop conditions as #dasblinkenlight suggested.
Note that if you have a performance critical loop, some of these methods could hurt performance. If in doubt, check what your compiler does and measure the elapsed time.

How to infinite loop or loop up to a limit without an if-else

I'm wondering if there's a way to write a function that takes one input, a max count for the number of times to loop, that will do an infinite loop if the number is negative, without using an if-else
i.e.
void func(int nAttempts) // if nAttempts <= 0, do an infinite loop
{
if ( nAttempts <= 0 )
{ // do an infinite loop
}
else
{ // do a loop up to nAttemtps
}
}
I'd like to know if there's a way to do that without an if-else
while ((nAttempts < 0) || (nAttempts-- > 0)) {...}
but... why? This makes your code less readable, where an if/else makes it pretty clear what your intentions are.
I take it this is some sort of a trick question? Here's my take:
void f(int n)
{
n < 0 ? []{ while(true); }() : [&]{ while(n--); }() ;
}
The loop itself has a conditional inside of it, it is not an explicit if, but it is a branch. The actual evaluation of that expression is turing complete as well due to lazy evaluation. As a result, this question is kind of nonsensical since even without an if statement, there is still a conditional statement taking place. However, the answer to your question is the following:
void optionalInfiniteLoop(int nAttempts){
while(nAttempts < 0 || nAttempts-- != 0){
...
}
}
Looking at this and understanding lazy evaluation, nAttempts < 0 is evaluated first. If it is true, the || does not need to run, and so it will never wrap the int around by subtracting too far. If it is false, then the second part of the while loop evaluates until nAttempts becomes 0. I don't think you'd save anything by doing this, and indeed, you may be forcing the computer to do slightly more work every iteration by checking nAttempts < 0 instead of just doing that once.
The performance is almost definitely not going to be measurable in the context of an application, and I think the above looks cleaner, but it's really more of a stylistic approach than a technical one.
void func( int nAttempts )
{
while (nAttempts)
{
// do stuff
--nAttempts;
}
}
Basically at the end of every iteration, you subtract one 'try'. When it hits 0 you stop. If it was already negative to begin with, it will become increasingly negative (though I suppose eventually it would overflow).

Is there only one way to implement a bubble sort algorithm?

I was trying to implement my own bubble sort algorithm without looking at any pseudo-code online, but now that I've successfully done it, mine code looks really different from the examples I see online. They all involve dealing with a swapped variable that is either true or false. My implementation does not include that at all, so did I NOT make a bubble sort?
Here is an example I see online:
for i = 1:n,
swapped = false
for j = n:i+1,
if a[j] < a[j-1],
swap a[j,j-1]
swapped = true
→ invariant: a[1..i] in final position
break if not swapped
end
Here is my implementation of it:
void BubbleSort(int* a, int size)
{
while (!arraySorted(a, size))
{
int i = 0;
while (i < (size-1))
{
if (a[i] < a[i+1])
{
i++;
}
else
{
int tmp = 0;
tmp = a[i+1];
a[i+1] = a[i];
a[i] = tmp;
i++;
}
}
}
}
It does the same job, but does it do it any differently?
As some people noted, your version without the flag works, but is needlessly slow.
However, if you take the original version and just throw away the flag (together with the break), it will still work. It's easy to see from the invariant that you conveniently posted.
The version without the break has roughly the same worst-case performance as with the break (worst case is for an array sorted in reverse order). It's better than the original one if you want an algorithm that is guaranteed to finish in a pre-defined time.
Wikipedia describes another idea for optimization of the bubble-sort, which includes throwing away the break.

Beginner for loop problem

[EDIT]Whoops there was a mistake in the code, and now all the responses to the question seem bizzare, but basically the for loop used to be, for(i=0; i<15; i++). I also edited to make the question more clear.[/EDIT]
I am trying to make a for loop, that checks a 16 element array, so it loops from 0 to 15. I then use the i variable later, however sometimes i == 16, which causes problems by being out of bounds.
I have a solution but it doesnt seem elegant, which makes me think I am missing something. I've tried while loops, but I can never get any loop to go from 0 to 15, and never end at a value greater than 15.
Is there any way to make a loop go and check all 16 elements of the array, while never being greater than 15 at the end of the loop?
int i;
for(i=0; i<16; i++)
{
someClass.someMethod(i);
if(someClass.Test())
{
break;
}
}
if (i == 16)
{
i = 15;
}
I suggest using some other variable other than i after your loop is finished. The criteria of using a for loop instead of a while loop is that you know beforehand exactly how many times a for loop will execute. If you already know this, just set some other variable to the ending value of your loop and use it instead of giving i a dual purpose.
int j = 15;
for(int i=0; i <= j; i++)
{
someClass.array[i];
}
// continue on using j, which value hasn't changed
Well for starters, your sample code loops from 0 to 14. But if you loop from 0 to 15, naturally i has to be 16 before the loop can end. What happens is it becomes 16, THEN your loop notices it's out of bounds and breaks out. If you want it to end at 15, honestly the easiest thing to do is just decrement just after the loop end.
i is incremented on last check to be 16, which is not less than 15, so loop exits with i being 16.
Maybe it's useful to know that:
for (before; check; after) { body }
it's the same as:
before
while(check) {
body
after
}
If you think at your for loop in that term, maybe you'll find out easily why i, at the exit, is 16.
There seems to be some fundamental flaws in your approach.
You shouldn't really use an index variable outside the scope of the loop.
You should use a variable or function to determine the limit of the loop.
It would be better to use iterators instead of numeric indexes.
Generic algorithms can remove the need for loops.
Just my $0.02.
So - if you're checking a 16 element array, normally you'd do this:
for(i=0; i<16; i++)
How for works, is it starts with the first statement of three:
i=0
Then it does your check, in the second statement:
i < 16 // True here, since 0 < 16
That happens before your loop. Then it runs the block of your loop with that set:
someClass.array[i]; //0
Finally, it does the final statement:
i++
Then it repeats the second and third statements, in a sequence.
Before the last run, i == 14, then it does i++, setting i to 15, and executes the block. Finally, it does i++, setting:
i==16
At this point, the condition is no longer true:
i < 16 // False, since i==16
At this point, your block does not execute, but i is still set to 16.
You must have missed something.
In this loop it wouldn't even hit 15, you'd need to say i <= 15, as soon as i = 14 it'd run once and bail.
The for loop is equivalent to the following while loop:
i = 0;
while(i < 16) {
someClass.array[i];
i++;
} // while
i needs to reach 16 to get out of the loop correctly.
Technically there are ways of writing the loop such that i is 15 on exiting the loop, but you shouldn't do them:
int i = 0;
while (1) {
someclass.someMethod(i);
if (i < 15) {
i++;
} else {
break;
}
}
Yes, it does what you ask. But the flow is horrible.
You cannot accomplish this with the built-in loop structures, and as Bill The Lizard said, you probably don't really want to reuse the for-loop variable.
But, if you really want to, here's a way to do it. The trick is to put the loop condition in the middle of the loop:
int i = 0;
while (true)
{
someclass.array[i];
if (i == 15)
break;
++i;
}
The key issue to understand here is that there are 17 different answers to the question "What value of i causes the test to succeed?". Either i can be in {0, 1, ..., 15}, or no value of i causes the test to succeed, which is denoted by i == 16 in this case. So if i is restricted to only 16 values, the question cannot be answered.
There are legitimate cases where you do not want to go past the last valid value. For instance, if you had 256 values and for some reason you only have one byte to count with. Or, as happened to me recently, you want to examine only every ith element of an array, and the last addition to your iterator takes you far beyond the end of the array. In these cases loop unrolling is necessary.
However, for this problem it would be cleaner to use a flag:
bool flag = false;
for (int i = 0; i < 15; ++i)
{
someClass.someMethod(i);
if (someClass.Test())
{
flag = true;
break;
}
}
Then it's clear whether or not the test ever succeeded.
If your loop terminates natuarally, rather than with a break, i will be 16. There's no way to avoid this. Your code is perfectly acceptable if what you want is for i to end up as 15 or less:
int i;
for (i=0; i<16; i++) {
someClass.someMethod(i);
if (someClass.Test())
break;
}
if (i == 16)
i = 15;
Anything that changes i from 16 to 15 after the loop body will do:
if (i == 16) i = 15;
i = (i == 16) ? 15 : i;
i = MAX (15,i); /* where MAX is defined :-) */
and so on.
However that assumes that i is going to be used for something meaningful as a post-condition with respect to that loop. I find that's rarely the case, people tend to re-initialize it before re-use (such as another for loop).
In addition, what you are doing makes it very difficult (impossible, even) to figure out as a post-condition, wheteher your loop terminated normally or whether it terminated prematurely because someClass.Test() returned true for i == 15. This means using i to make further decision is fraught with danger.
My question would be: Why do you think you need to leave i as 15 or less?
I am trying to make a for loop, that
checks a 16 element array, so it loops
from 0 to 15. I then use the i
variable later, however sometimes i ==
16, which causes problems by being out
of bounds.
You need to check for the case where your for loop didn't break, because this information determines whether or not whatever you wanted to do with i is valid.
There are a couple of ways to do this. One is to keep track of it in a bool, such as "foundClass" or "testSucceeded". Default it to false, then set it to true on your break. Enclose any uses of i later in the function in "if (foundClass) { }" blocks.
Another is to just do what you've done. Although your fallback doesn't look right at all. If you're setting i to 15, you're lying to your code and telling it that someClass.Test() succeeded for i == 15, which isn't true. Avoid setting the value to something that's wrong just so your code doesn't error later on. It's much better to put bounds checks around the actual usage of i later in the code.
for(int i=0; i<17; i++)
{
if(i<16)
{
someClass.someMethod(i);
if(someClass.Test())
{
break;
}
}
else if(i==16)
{
i=15;
}
}
if you say you have an array with 16 elements, you don't have to define that, use the array to get that info (DO NOT DUPLICATE INFORMATION)
afterwards if you want to get the last index again use the array to get that info.
for(int i = 0; i < myArray.length; ++i){
myArray[i].somemethod();
}
// lastindex = myArray.length-1;