Ja, Compiler können Inline Virtual Destructor in diesem Fall. Lassen Sie uns ein Codebeispiel betrachten:
#include <iostream>
int global = 0;
class A {
public:
virtual void foo() { std::cout << "A" << std::endl; }
virtual ~A() { ++global; }
};
class B : public A {
public:
virtual void foo() { std::cout << "B" << std::endl; }
virtual ~B() { --global; }
};
int main() {
{
B b[5];
b[0].foo();
}
std::cout << "global: " << global << std::endl;
return 0;
}
https://godbolt.org/g/PWEVW8
Wie Sie Klirren 3.8 mit O3 Optimierung sehen nicht immer Code für Klassen (gcc 6.1 mit O3 generieren Klasse B erzeugen, wird aber Inline destructor sowieso):
main: # @main
pushq %r14
pushq %rbx
pushq %rax
movl std::cout, %edi
movl $.L.str.2, %esi
movl $1, %edx
callq std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
movq std::cout(%rip), %rax
movq -24(%rax), %rax
movq std::cout+240(%rax), %rbx
testq %rbx, %rbx
je .LBB0_9
cmpb $0, 56(%rbx)
je .LBB0_3
movb 67(%rbx), %al
jmp .LBB0_4
.LBB0_3:
movq %rbx, %rdi
callq std::ctype<char>::_M_widen_init() const
movq (%rbx), %rax
movl $10, %esi
movq %rbx, %rdi
callq *48(%rax)
.LBB0_4: # %_ZNKSt5ctypeIcE5widenEc.exit2
movsbl %al, %esi
movl std::cout, %edi
callq std::basic_ostream<char, std::char_traits<char> >::put(char)
movq %rax, %rdi
callq std::basic_ostream<char, std::char_traits<char> >::flush()
movl std::cout, %edi
movl $.L.str, %esi
movl $8, %edx
callq std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
movl global(%rip), %esi
movl std::cout, %edi
callq std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
movq %rax, %r14
movq (%r14), %rax
movq -24(%rax), %rax
movq 240(%r14,%rax), %rbx
testq %rbx, %rbx
je .LBB0_9
cmpb $0, 56(%rbx)
je .LBB0_7
movb 67(%rbx), %al
jmp .LBB0_8
.LBB0_7:
movq %rbx, %rdi
callq std::ctype<char>::_M_widen_init() const
movq (%rbx), %rax
movl $10, %esi
movq %rbx, %rdi
callq *48(%rax)
.LBB0_8: # %std::ctype<char>::widen(char) const [clone .exit]
movsbl %al, %esi
movq %r14, %rdi
callq std::basic_ostream<char, std::char_traits<char> >::put(char)
movq %rax, %rdi
callq std::basic_ostream<char, std::char_traits<char> >::flush()
xorl %eax, %eax
addq $8, %rsp
popq %rbx
popq %r14
retq
.LBB0_9:
callq std::__throw_bad_cast()
pushq %rax
movl std::__ioinit, %edi
callq std::ios_base::Init::Init()
movl std::ios_base::Init::~Init(), %edi
movl std::__ioinit, %esi
movl $__dso_handle, %edx
popq %rax
jmp __cxa_atexit # TAILCALL
global:
.long 0 # 0x0
.L.str:
.asciz "global: "
.L.str.2:
.asciz "B"
Ist das ein tatsächliches Problem, das Sie mit Code demonstrieren könnten, oder ist Ihre Frage, warum bestimmte Optimierungen nicht gemacht werden? – Soren
Der Compiler kann nach Möglichkeit jede virtuelle Funktion (Inline, Elide, ...) optimieren. –
Sehen Sie sich * devirtualization * an. – Jarod42