The compiler calculates the size of the function's variables and upon entry the function adjusts the stack pointer by that much. At this point nothing is initialised though, it only contains garbage data.
Then upon entry to each scope block (curly braces), variables inside that scope block are initialised (their constructor is called if one was provided).
At the end of the scope block, those variables are destructed (their destructor is called if one was provided), but the stack space for them tends to exist until the end of the function.
It's also possible for variables of non-overlapping scope to re-use the same portion of the stack.