0
votes

Here's an example:

while (i < 10)
    {
        int j = 1;
        string k = "hello.";
    }

j is a primitive data type and k is an object. According to Do built-in types have default constructors?,

So non-class types (including fundamental types, array types, reference types, pointer types, and enum types) do not have constructors.

And according to Declaring Variables inside Loops, good practice or bad practice? (2 Parter),

the constructor and destructor must be executed at each iteration in the case of an object (such as std::string).

However, variable declaration within the while loop C/C++ says,

while(i--)
    {
      int i=100; // gets created every time the loop is entered
      i--;
      printf("%d..",i);
    } // the i in the loop keeps getting destroyed here

I've learned that when a function is called (such as main() by the operating system), all local variables are created at the start of the function and destroyed at the end of the function. The above while loop quote is saying that the primitive data type i is being created when it is declared in the while loop block and destroyed at the end of the while loop block for each iteration.

Is this really true? #1 Are primitive data types declared in the while loop block being allocated for each iteration of the while loop? #2 Am I wrong to assume that these declarations in a while loop should be created at the start of the function the while loop block is contained in?

I'm looking for a detailed explanation, not just yes or no.

3
For #1, depending on the compiler, the code could be optimized so that i is declared outside of the while loop but assigned 100 inside it.squill25
To my knowledge, a primitive type such as int will be allocated space on the stack, and that space will simply be re-used each time round the loop. The value 100 in your example will just be re-copied into it at the start of each loop iteration. Try taking a look at the assembly code generated by your compiler, or step through with the assembly inline in the debugger (if your IDE supports that). You'll see exactly what's going on.Baldrick

3 Answers

3
votes

The program must behave as if it is reallocated (and then deallocated) every time through the loop.

The mechanism by which the program exhibits that behavior is completely up to the compiler. In many cases, no space will ever be allocated for the variable at all, or it might not even exist at all! (such as j in your first example)

If space does get allocated, I think it's typical that space is reserved when the function containing the loop gets called. (and that space isn't necessarily exclusively reserved)

3
votes

Yes, when you declare a variable inside the loop, the program behaves as if the variable was created and destroyed on every loop iteration. So if the variable has class type, the program behaves as if its constructor and destructor were called every time.

However, due to optimization, unobservable behavior can be removed, so the first loop can just be optimized away completely, and the second loop can be optimized to something like

while(i--)
    printf("%d..", 99);

So it may happen that no actual variable is created.

1
votes

Logically, yes, the variables are being created at the start of the loop body for every iteration of the loop, and destroyed at the end.

In your first example, the constructor of std::string (actually std::basic_string<char> which is what std::string is) will be invoked for every iteration, as will the destructor. Similarly j is being created and set to 1 for every iteration.

In the second example, i will be printed with the value 99 for the same reason.

Compilers do have some leeway in this. If they can detect there is no effect of repeatedly creating and destroying, they can keep the variable alive, and simply reinitialise it for every loop iteration. They can even eliminate variables completely (e.g. just print 99 repeatedly, and not create the variable). However, such things cannot be relied on, and a program cannot test to see if it happens.