C++ C++;从程序集输出的角度理解虚拟析构函数如何增加类型的大小
我试图更深入地理解为什么以下程序的输出是这样的(请参见下文)。同时,我试图理解它与程序的汇编版本之间的关系。主要是,汇编代码中的类型在哪里?是什么导致一个比另一个大?使子类大于测试类的虚拟表中的何处 代码C++ C++;从程序集输出的角度理解虚拟析构函数如何增加类型的大小,c++,gnu-assembler,C++,Gnu Assembler,我试图更深入地理解为什么以下程序的输出是这样的(请参见下文)。同时,我试图理解它与程序的汇编版本之间的关系。主要是,汇编代码中的类型在哪里?是什么导致一个比另一个大?使子类大于测试类的虚拟表中的何处 代码 #include <iostream> class parent { int glove; public: parent() {} virtual ~parent() {} }; class child : public parent { int ball; p
#include <iostream>
class parent {
int glove;
public:
parent() {}
virtual ~parent() {}
};
class child : public parent {
int ball;
public:
child() {}
~child() {}
};
class test {
int test1;
int test2;
public:
test() {}
};
int main() {
std::cout << "Size of child is " << sizeof(child) << std::endl;
std::cout << "Size of test is " << sizeof(test) << std::endl;
}
组装
.file "test.cpp"
.local _ZStL8__ioinit
.comm _ZStL8__ioinit,1,1
.section .rodata
.LC0:
.string "Size of child is "
.LC1:
.string "Size of test is "
.text
.globl main
.type main, @function
main:
.LFB974:
.cfi_startproc
.cfi_personality 0x0,__gxx_personality_v0
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $16, %esp
movl $.LC0, 4(%esp)
movl $_ZSt4cout, (%esp)
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl $12, 4(%esp)
movl %eax, (%esp)
call _ZNSolsEj
movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
movl %eax, (%esp)
call _ZNSolsEPFRSoS_E
movl $.LC1, 4(%esp)
movl $_ZSt4cout, (%esp)
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
movl $8, 4(%esp)
movl %eax, (%esp)
call _ZNSolsEj
movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
movl %eax, (%esp)
call _ZNSolsEPFRSoS_E
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE974:
.size main, .-main
.type _Z41__static_initialization_and_destruction_0ii, @function
_Z41__static_initialization_and_destruction_0ii:
.LFB984:
.cfi_startproc
.cfi_personality 0x0,__gxx_personality_v0
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
cmpl $1, 8(%ebp)
jne .L5
cmpl $65535, 12(%ebp)
jne .L5
movl $_ZStL8__ioinit, (%esp)
call _ZNSt8ios_base4InitC1Ev
movl $_ZNSt8ios_base4InitD1Ev, %eax
movl $__dso_handle, 8(%esp)
movl $_ZStL8__ioinit, 4(%esp)
movl %eax, (%esp)
call __cxa_atexit
.L5:
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE984:
.size _Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii
.type _GLOBAL__I_main, @function
_GLOBAL__I_main:
.LFB985:
.cfi_startproc
.cfi_personality 0x0,__gxx_personality_v0
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
movl $65535, 4(%esp)
movl $1, (%esp)
call _Z41__static_initialization_and_destruction_0ii
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE985:
.size _GLOBAL__I_main, .-_GLOBAL__I_main
.section .ctors,"aw",@progbits
.align 4
.long _GLOBAL__I_main
.weakref _ZL20__gthrw_pthread_oncePiPFvvE,pthread_once
.weakref _ZL27__gthrw_pthread_getspecificj,pthread_getspecific
.weakref _ZL27__gthrw_pthread_setspecificjPKv,pthread_setspecific
.weakref _ZL22__gthrw_pthread_createPmPK14pthread_attr_tPFPvS3_ES3_,pthread_create
.weakref _ZL20__gthrw_pthread_joinmPPv,pthread_join
.weakref _ZL21__gthrw_pthread_equalmm,pthread_equal
.weakref _ZL20__gthrw_pthread_selfv,pthread_self
.weakref _ZL22__gthrw_pthread_detachm,pthread_detach
.weakref _ZL22__gthrw_pthread_cancelm,pthread_cancel
.weakref _ZL19__gthrw_sched_yieldv,sched_yield
.weakref _ZL26__gthrw_pthread_mutex_lockP15pthread_mutex_t,pthread_mutex_lock
.weakref _ZL29__gthrw_pthread_mutex_trylockP15pthread_mutex_t,pthread_mutex_trylock
.weakref _ZL31__gthrw_pthread_mutex_timedlockP15pthread_mutex_tPK8timespec,pthread_mutex_timedlock
.weakref _ZL28__gthrw_pthread_mutex_unlockP15pthread_mutex_t,pthread_mutex_unlock
.weakref _ZL26__gthrw_pthread_mutex_initP15pthread_mutex_tPK19pthread_mutexattr_t,pthread_mutex_init
.weakref _ZL29__gthrw_pthread_mutex_destroyP15pthread_mutex_t,pthread_mutex_destroy
.weakref _ZL30__gthrw_pthread_cond_broadcastP14pthread_cond_t,pthread_cond_broadcast
.weakref _ZL27__gthrw_pthread_cond_signalP14pthread_cond_t,pthread_cond_signal
.weakref _ZL25__gthrw_pthread_cond_waitP14pthread_cond_tP15pthread_mutex_t,pthread_cond_wait
.weakref _ZL30__gthrw_pthread_cond_timedwaitP14pthread_cond_tP15pthread_mutex_tPK8timespec,pthread_cond_timedwait
.weakref _ZL28__gthrw_pthread_cond_destroyP14pthread_cond_t,pthread_cond_destroy
.weakref _ZL26__gthrw_pthread_key_createPjPFvPvE,pthread_key_create
.weakref _ZL26__gthrw_pthread_key_deletej,pthread_key_delete
.weakref _ZL30__gthrw_pthread_mutexattr_initP19pthread_mutexattr_t,pthread_mutexattr_init
.weakref _ZL33__gthrw_pthread_mutexattr_settypeP19pthread_mutexattr_ti,pthread_mutexattr_settype
.weakref _ZL33__gthrw_pthread_mutexattr_destroyP19pthread_mutexattr_t,pthread_mutexattr_destroy
.ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-3)"
.section .note.GNU-stack,"",@progbits
它只是向您的子类添加一个指向虚拟表的指针,在您的特定平台上正好是32位的。虚拟方法调度完全是一个实现问题(即特定于编译器的)。该标准没有说明应该如何实现,它可以使用VTables、black magic或谁知道还有什么 话虽如此,我们只能猜测会发生什么 是什么导致一个比另一个大?使子类大于测试类的虚拟表中的何处 假设编译器实际使用VTable,实现它们的通常方法是在且仅当类具有虚拟方法时(与它们是普通方法还是类的析构函数无关)向每个对象添加指向VTable的隐藏指针。因此,您的
家长
类实际上在引擎盖下看起来是这样的:
class parent {
VTable* hidden_vtable_ptr; // this is likely to be why child is bigger than test
int glove;
public:
parent() {}
virtual ~parent() {}
};
请注意,无论是使用虚拟析构函数还是仅使用虚拟方法,都会发生这种情况:
struct test_pod {
int t[2];
};
struct test_dtor {
int t[2];
virtual ~test_dtor() {}
};
struct test_method {
int t[2];
virtual void foo() {}
};
int main() {
std::cout << sizeof(test_pod) << std::endl; // 8
std::cout << sizeof(test_dtor) << std::endl; // 16
std::cout << sizeof(test_method) << std::endl; // 16
return 0;
}
struct test\u pod{
int t[2];
};
结构测试{
int t[2];
虚拟~test_dtor(){}
};
结构测试法{
int t[2];
虚拟void foo(){}
};
int main(){
std::cout这里有一些。实际上,VTable的隐藏指针在基本父类中,派生的子类继承它。
struct test_pod {
int t[2];
};
struct test_dtor {
int t[2];
virtual ~test_dtor() {}
};
struct test_method {
int t[2];
virtual void foo() {}
};
int main() {
std::cout << sizeof(test_pod) << std::endl; // 8
std::cout << sizeof(test_dtor) << std::endl; // 16
std::cout << sizeof(test_method) << std::endl; // 16
return 0;
}