Distribution of storage of local variables inside a block in C ++

I want to know at what point the compiler allocates storage for local variables inside a block. How to go and switch through the constructor?

class Tree {/*...*/} ... void foo (int i){ if (i < 10) goto label; //illegal: cannot jump past a ctor Tree t (45); label: switch (i){ case 1: Tree t2 (45); break; case 2: //illegal: cannot jump past ctor Tree t3 (45); break; } } 

Although the code above does not work for custom objects, it works if I replace them with inline objects. Why is this?

Edit: Inline objects like int, char, etc. Errors I get (g ++ 4.5 on ubuntu):

 jumpPastConstructor.c++: In function 'void foo(int)': jumpPastConstructor.c++:26:3: error: jump to label 'label' jumpPastConstructor.c++:24:20: error: from here jumpPastConstructor.c++:25:10: error: crosses initialization of 'Tree t' jumpPastConstructor.c++:31:16: error: jump to case label jumpPastConstructor.c++:29:25: error: crosses initialization of 'Tree t2' 
+6
c ++ constructor
source share
6 answers

6.7 / 3:

It can be moved to a block, but not in such a way as to bypass initialization declarations. a program that jumps from the point where the local variable with the automatic storage period is not the point at which it is located, poorly formed if the variable does not have a POD type (3.9) and is declared without an initializer (8.5).

It doesn’t matter when the storage is allocated, but when the constructor is called. The problem that jumped over the constructor was a problem, so it was forbidden. (POD types without an initializer do not need any construction, so they are allowed.)

+13
source share

The first part of the question is simple: most compilers map all local distributions to a single stack distribution and then split that allocation. Initialization occurs only when they fall into scope or they are explicitly initialized.

Your example is pretty bad in terms of coding, when you go over the point where x enters the scope, so the constructor will never be called (this is one of the reasons why goto is bad ) and why your compiler tells you to stop trying to abuse it . However, some types may be left uninitialized, such as the int , float and so on. Instead, you will receive a warning, so not everyone gives an error if you jump over its initialization (constructor).

+4
source share

Converted to compiled code in xx.cpp:

 class C { int i; public: C(int i_val = 0) : i(i_val) { } }; int main() { int someval = 2; goto label; //error C x; label: switch (someval) { case 1: C x2; break; case 2: //error C x3; break; } } 

and compiled, as shown in g ++ 4.6.0 on MacOS X 10.6.8, throws the indicated errors:

 $ g++ -Wall -Wextra -c xx.cpp xx.cpp: In function 'int main()': xx.cpp:13:1: error: jump to label 'label' [-fpermissive] xx.cpp:11:10: error: from here [-fpermissive] xx.cpp:12:7: error: crosses initialization of 'C x' xx.cpp:19:14: error: jump to case label [-fpermissive] xx.cpp:17:15: error: crosses initialization of 'C x2' $ 

There is a default constructor for each of the variables x , x2 and x3 .

And the C ++ standard just says that you are not allowed to go into a block after a construction variable. What will work:

 class C { int i; public: C(int i_val = 0) : i(i_val) { } }; int main() { int someval = 2; goto label; //error { C x; } label: switch (someval) { case 1: { C x2; } break; case 2: //error { C x3; } break; } } 

With three additional pairs of curly braces, you no longer jump into blocks where variables are declared and initialized, so the code is legal and compiles cleanly on the command line shown earlier.

+3
source share

The solution here: Add brackets for each CASE

 switch (i){ case 1:{ Tree t2 (45); break; } case 2: {//illegal: cannot jump past ctor Tree t3 (45); break; } 

}

I do not know what kind of craziness it is !!! But Add {and} can solve this problem!

+1
source share

You cannot goto or case for all constructors. Inline objects do not have constructors.

The compiler knows when it introduces the function, what is the general need for its local variables, and it moves the stack pointer to place them. This memory is not initialized.

It calls constructors and destructors during a function flow as needed. That is why you cannot use goto or case like this - it destroys invariants. Expressions such as break invoke destructors as needed, for example, for a loop, and everything works fine.

0
source share

I came here because I had the same problem.
What helped me was to abandon the "Tree" outside of case .
And not Tree t2 (45); , and place Tree t2; to switch .
And t2 (45); inside case 1 .

And then you need to do the same for Tree t3 (45); .

0
source share

All Articles