First, this really has nothing to do with the OOP paradigm. It's simply about how to properly define/initialize an array.
Doing:
1 2 3
|
int Q;
cin>>Q;
int a[Q];
|
is simply not allowed in standard C++. It's a GNU extension called "VLA" (Variable-Length Array, which actually is standard in C, but still potentially dangerous to use).
The only difference with putting it in a class is that a is initialized when the object is initialized, so it's already too late to give the array a size; thus a is always allocated with a size of 0.
About your code:
Again, it's simply undefined behavior. So what you're doing is simply not allowed, regardless of if it happens to work.
I don't know assembly very well at all, so I'm actually guessing here, but this is what the GNU assembly looks like:
using
g++ -S main.cpp -o main_asm.s |
(Note: my g++ compiler is 64-bit, yours might be 32-bit, but so the registers might have different names, but the behavior should be similar)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
main:
.LFB1525:
pushq %rbp
.seh_pushreg %rbp
movq %rsp, %rbp
.seh_setframe %rbp, 0
subq $48, %rsp
.seh_stackalloc 48
.seh_endprologue
call __main
;
; ... (removed for brevity)
;
leaq -16(%rbp), %rax
movq %rax, %rcx
call _ZN6Number11greatestfacEv
movl $0, %eax
addq $48, %rsp
popq %rbp
ret
.seh_endproc
.def __tcf_0; .scl 3; .type 32; .endef
.seh_proc __tcf_0
|
Note that the sizeof(Number) in your program is 16, because you have 4 ints, each int taking up 4 bytes, but a[] takes up 0 size, although the address of a goes past what was allocated for your Number object, so already something is amiss.
In your greatestfac number, it compares a value to 2, and if it isn't equal to 2, it does a jump.
1 2
|
cmpl $2, %eax
jne .L21
|
And .L21 looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
.L21:
leaq .LC9(%rip), %rdx
movq .refptr._ZSt4cout(%rip), %rcx
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movq %rax, %rcx
movq 16(%rbp), %rax
movl 12(%rax), %eax
leal -2(%rax), %edx
movq 16(%rbp), %rax
movslq %edx, %rdx
addq $4, %rdx
movl (%rax,%rdx,4), %eax
movl %eax, %edx
call _ZNSolsEi
|
My guess is that something within the .LN21 logic (i.e. greater than 2 factors) is corrupting the stack, and causing the program to fail when it eventually tries to pop off the stack.
If you actually changed your class to look like, e.g.
1 2 3 4
|
class Number {
int Q,N,R,F, dummy;
int a[];
};
|
sizeof(Number) will now be 20.
You'll notice that the assembly now will do
subq $64, %rsp
instead of
subq $48, %rsp
,
giving you 16 more bytes to work with (4 ints).
So, entering 4 will now not crash your program.
Now, even entering 16 won't crash your program.
But entering something that produces a longer result, like 32, will still crash your program.
If you wanted to explore exactly which part of the assembly is failing, you might want to look into a tool like gdb or related tools.
https://stackoverflow.com/a/55935724/8690169