A "local" stack, as that comment uses it, means stack implicitly declared as a local variable. I would differentiate it from the call stack by calling it an "explicit" stack.
Iterating on an explicit stack can be faster than recursion in languages that don't support recursion related optimizations such as tail recursion. Or a language may have limited stack depth.
Here is a good explanation with an example by Eric Lippert.
The point is that this
is an implicit formal parameter (containing the address of the object whose method you are calling). It is not a local variable.
Look at the generated code of your program. I compiled (on Linux/Debian/Sid/x86-64 with GCC 4.9.1) your example arman.cc
with
gcc -O1 -fverbose-asm -S arman.cc
and got the function main
below
.globl main
.type main, @function
main:
.LFB512:
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
.cfi_lsda 0x3,.LLSDA512
pushq %rbx #
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
subq $48, %rsp #,
.cfi_def_cfa_offset 64
movq $0, 16(%rsp) #, MEM[(struct _Vector_impl *)&vec]._M_start
movq $0, 24(%rsp) #, MEM[(struct _Vector_impl *)&vec]._M_finish
movq $0, 32(%rsp) #, MEM[(struct _Vector_impl *)&vec]._M_end_of_storage
movq $0, (%rsp) #, MEM[(struct A *)&__x]
movq %rsp, %rcx #,
movl $100, %edx #,
movl $0, %esi #,
leaq 16(%rsp), %rdi #, tmp92
.LEHB0:
call _ZNSt6vectorI1ASaIS0_EE14_M_fill_insertEN9__gnu_cxx17__normal_iteratorIPS0_S2_EEmRKS0_ #
.LEHE0:
movq 16(%rsp), %rdi # MEM[(struct _Vector_base *)&vec]._M_impl._M_start, D.10014
testq %rdi, %rdi # D.10014
je .L34 #,
call _ZdlPv #
jmp .L34 #
.L33:
movq %rax, %rbx #, tmp91
movq 16(%rsp), %rdi # MEM[(struct _Vector_base *)&vec]._M_impl._M_start, D.10014
testq %rdi, %rdi # D.10014
je .L32 #,
call _ZdlPv #
.L32:
movq %rbx, %rdi # tmp91,
.LEHB1:
call _Unwind_Resume #
.LEHE1:
.L34:
movl $0, %eax #,
addq $48, %rsp #,
.cfi_def_cfa_offset 16
popq %rbx #
.cfi_def_cfa_offset 8
ret
.cfi_endproc
You see that some space for your vec
is allocated on the stack (e.g. with subq $48, %rsp
etc...) and then the address of that zone on the stack is passed as the this
formal argument (using the usual x86-64 ABI conventions, which dictates (p 20) that the first argument of function is passed thru register %rdi
) so you could say that this
is, at the beginning of some member function, in the register %rdi
...
IIRC, the wording of the C++ standard are vague enough to permit the this
argument to be passed in a special way, but all the ABIs I heard of are passing it exactly as the first (pointer) argument of usual C functions.
BTW, you should trust the compiler and let it pass this
as convenient and as prescribed by ABI specifications.
Best Answer
In addition to what Dirk said, an important use of stack frames is to save previous values of registers so that they can be restored after a function call. So, even on processors where registers are used for passing parameters, returning a value, and saving the return address, the values of those registers are saved on the stack before a function call so that they can be restored after the call. This allows one function to call another without overwriting its own parameters or forgetting its own return address.
So, calling a function B from function A on a typical "generic" system might involve the following steps:
This is by no means the only way function calls can work (and I may have a step or two out of order), but it should give you an idea of how the stack is used to let the processor handle nested function calls.