Reputation: 5533
Currently I'm reading Think in C++
.
I'm confused about the conditional storage allocation for an object.
As the code below, the goto
and switch
generate warning or an error.
But if-else
works fine, which is conditionally passed through during execution.
So why there is no warning or error for if-else
?
/* crosses initializaion error */
#include <iostream>
using namespace std;
class X {
public:
X();
};
X::X() {}
void f(int i) {
if (i > 2) {
X x1;
} else {
X x2; // why conditionally executed works fine?
}
if (i > 2) {
goto jjump1;
}
//X x3; // error coused by goto
{X x3; //works fine}
jjump1:
X x4;
switch(i) {
// case 1: X x5; break;
//case 2: X x6; break; // error coused by switch
{case 1: X x5; break;}
{case 2: X x6; break;}// solved
}
}
int main() {
f(1);
return 0;
}
UPDATE:
C++ doing so is to guarantee that an object cannot be created unless it is also initialized.
But in the case of if-else
how can both part of it be initialized as only one part of it will be go through?
As the C++ is following the practice in C of allocating the storage for a scope at the opening brace of that scope.
Here is my thought(I don't know what's wrong..):
But it's the same for switch
and goto
, only the token case need to be initialized but there is crosses initialization error. The if-else
and switch
both obey initializing the token branch only.
At last, I figured out the key word is scope
. As the C++ is following the practice in C of allocating the storage for a scope at the opening brace of that scope. So the A program that jumps87 from a point where a variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has scalar type, class type with a trivial default constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the preceding types and is declared without an initializer rule ensure that variables are initialized once allocated.
Thank you all.
Upvotes: 2
Views: 642
Reputation: 158469
You are not allowed to jump past the declaration of a variable unless it is scalar or it has a trivial default constructor, this is covered in the draft C++ standard section 6.7
:
It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps87 from a point where a variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has scalar type, class type with a trivial default constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the preceding types and is declared without an initializer (8.5).
In the case of the switch one way to avoid this problem would be to create a scope using {}
at each label like this:
switch(i)
{
case 1: { X x5; break; }
case 2: { X x6; break; }
}
Upvotes: 4