Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

storage allocation in c++

I'm reading thinking in c++ chapter 6 initialization & cleanup. The author said that:

It's actually more likely that the compiler will follow the practice in C of allocating all the storage for a scope at the opening brace of that scope. It doesn't matter because, as a programmer, you can't access the storage until it has been defined. Although the storage is allocated at the beginning of the block, the constructor call doesn't happen until the sequence point where the object is defined because the identifier isn't available until then. The compiler even checks to make sure that you don't put the object definition where the sequence point only conditionally passes through it, such as in a switch statement or somewhere a goto can jump past it.

And then the author gives an example as following:

class X {
public:
  X();
};

X::X() {}

void f(int i) {
  if(i < 10) {
   //! goto jump1; // Error: goto bypasses init
  }
  X x1;  // Constructor called here
 jump1:
  switch(i) {
    case 1 :
      X x2;  // Constructor called here
      break;
  // case 2 : // Error: case bypasses init
      X x3;  // Constructor called here
      break;
  }
} 

int main() {
  f(9);
  f(11);
}///:~

I don't understand why the above code is OK? According to my understanding, x2 can be bypassed initialization if i is not 1.

Supplement:

This sentence "It'a actually more likely that the compiler will follow the practice in C of allocating all the storage for a scope at the opening brace of that scope." also confused me.

According to the author's description, at the opening brace of the switch, the compiler has already allocated space for x2 and x3. If this is the case, there is an opportunity for x2 to be uninitialized(case 1 is not satisfied).

like image 856
Fihop Avatar asked Feb 20 '13 21:02

Fihop


2 Answers

According to my understanding, x2 can be bypassed initialization if i is not 1.

No, either the case 1 is executed, and x2 is defined and then destroyed at the end of the switch block, or no case is executed and the entire switch block does nothing, so x2 is not in scope, so it isn't initialized but it can't be referred to either. So either it exists and is safe to use, or it doesn't exist.

like image 199
Jonathan Wakely Avatar answered Oct 11 '22 00:10

Jonathan Wakely


C++ object initialization and destruction semantics are completely jump-safe (exception, goto , switch and loop constructs included).

(The only notable exception is inherited from the C standard library (setjmp/longjmp))

6.6 Jump statements

2 On exit from a scope (however accomplished), objects with automatic storage duration (3.7.3) that have been constructed in that scope are destroyed in the reverse order of their construction. [ Note: For temporaries, see 12.2. —end note ] Transfer out of a loop, out of a block, or back past an initialized variable with automatic storage duration involves the destruction of objects with automatic storage duration that are in scope at the point transferred from but not at the point transferred to. (See 6.7 for transfers into blocks). [ Note: However, the program can be terminated (by calling std::exit() or std::abort() (18.5), for example) without destroying class objects with automatic storage duration. —end note ]

like image 24
sehe Avatar answered Oct 11 '22 00:10

sehe