The whole point of avoiding dynamic memory allocation is that if your program has enough memory to complete initialization, then you know for a certainty you won't hit an out of memory condition in the middle of your program, under some borderline set of conditions you hadn't thought of.
Writing your own memory manager defeats that benefit. In fact, it makes it less safe. Instead of running out of heap with the built in memory manager that is highly tested, optimized, and used by millions of programmers, you are instead running out of memory on an untested memory manager, written by programmers who probably haven't written a memory manager before, and used only by you.
If you're getting stack overflows from your object being too large, the solution is to not allocate the object on the stack, as in your static test t;
or static float m_bigMatrix[3000000];
. Yes, it's annoying. Yes, it goes against your instincts from what you've been taught are best practices on non-critical systems. That's just how it goes.
One compromise I've seen is to only avoid dynamic deallocation, and make sure to perform all your dynamic allocation when the program first starts up. This makes it feel more natural, but still gives you the benefit of a known memory bound. However, it's much more difficult to audit. When I worked before on critical systems, this was only allowed in very exceptional circumstances.
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
Note: implementations don't have to have 'stacks' and 'heaps' but they are pretty common implementation artifacts.
If you create a "local" instance of MyClass (ie. an automatic variable) then its memory will be on the stack. The 'others' member variable will typically take up a couple of 'words' in memory (eg. a 'word' might be 32 bits); one for the vectors size variable and a pointer to dynamic memory for the vector's members. The dynamic memory will be allocated on the heap by something like malloc().