面试中经常遇到类似多态,虚继承,RTTI,dynamic_cast实现原理之类的问题,这块需要对C++底层内存模型比较理解。C++由于没有存储对象元信息(java反射基础),要支持多态,多继承特性,导致C++对象内存模型异常复杂。
一. 继承内存模型
1. 基类
struct B { long b; virtual void foo(){} virtual void bar(){} };
gcc的-fdump-class-hierarchy选项,它可以用于输出C++程序的虚表结构
g++ -fdump-class-hierarchy -fsyntax-only test.c,在当前目录生成test.c.002t.class class文件。
结构分析:
cat test.c.002t.class Vtable for B B::_ZTV1B: 4u entries 0 (int (*)(...))0 // offset 8 (int (*)(...))(& _ZTI1B) // RTTI typeinfo 16 B::foo // virtual table 24 B::bar Class B size=16 align=8 base size=16 base align=8 B (0x7ffa3355aaf0) 0 vptr=((& B::_ZTV1B) + 16u)
2. 多重继承
struct A { int a; }; struct B : public A { virtual void foo(){} }; struct C : public A { virtual void bar(){} }; struct D: public B, public C { virtual void qux(){} }; // 测试 D d;
gdb调试查看对象成员:
(gdb) p d $1 = {<B> = {<A> = {a = 4195632}, _vptr.B = 0x400830}, <C> = {<A> = {a = 0},_vptr.C = 0x400850}, <No data fields>} (gdb) p sizeof(d) $2 = 32 (gdb) x/32xb &d 0x7fffffffdf10: 0x30 0x08 0x40 0x00 0x00 0x00 0x00 0x00 0x7fffffffdf18: 0x30 0x05 0x40 0x00 0x00 0x00 0x00 0x00 0x7fffffffdf20: 0x50 0x08 0x40 0x00 0x00 0x00 0x00 0x00 0x7fffffffdf28: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
B 和 C各自拥有一个A成员,sizeof(D) = 4(+4padding) + 8 + 4(+4padding) + 8 = 32,D有两个A成员,对象尺寸膨胀,同时代码对基类成员引用容易出现二义性。
3. 虚继承
struct B : virtual public A { virtual void foo(){} }; struct C : virtual public A { virtual void bar(){} };
gdb调试:
(gdb) p d $1 = {<B> = {<A> = {a = -8176}, _vptr.B = 0x400838}, <C> = {_vptr.C = 0x400860}, <No data fields>} (gdb) p sizeof(d) $2 = 24 (gdb) x/24xb &d 0x7fffffffdf10: 0x38 0x08 0x40 0x00 0x00 0x00 0x00 0x00 0x7fffffffdf18: 0x60 0x08 0x40 0x00 0x00 0x00 0x00 0x00 0x7fffffffdf20: 0x10 0xe0 0xff 0xff 0xff 0x7f 0x00 0x00
二. dynamic_cast 实现
Derive *d = dynamic_cast<Derive*>(base);
从上图可知,虚表中包含typeinfo信息,dynamic_cast会查找虚表中是否包含Derive 的RTTI信息,有则返回该基类实例。由此可见,该操作符会有一定性能损耗。
RTTI 信息是包含在虚表内,如果没有virtual 函数,则不会生成虚表,此时dynamic_cast 转换会怎样?
test.c:34: error: cannot dynamic_cast ‘base’ (of type ‘class Base*’) to type ‘class Derive*’ (source type is not polymorphic)
结果编译出错。
三. 多重继承对象大小
// 基类 class Concrete1 { public: int val; char c1; }; class Concrete2: public Concrete1 { public: char c2; }; class Concrete3: public Concrete2 { public: char c3; }; // 测试 Concrete3 c3; c3.val = 1; c3.c1 = 'A'; c3.c2 = 'B'; c3.c3 = 'C';
sizeof(Concrete3) != 16?
按照《深入探索C++对象模型》书里介绍,Concrete2/Concrete3均会添加padding,因此sizeof为16。我们在gcc 4.4.7上验证下该问题。
(gdb) p c3 $1 = {<Concrete2> = {<Concrete1> = {val = 1, c1 = 65 'A'}, c2 = 66 'B'}, c3 = 67 'C'} (gdb) p sizeof(c3) $2 = 12 (gdb) x/12xb &c3 0x7fffffffde60: 0x01 0x00 0x00 0x00 0x41 0x7f 0x00 0x00 0x7fffffffde68: 0x42 0x43 0x60 0x00
c3使用了padding区域,总长度因此为12,与书上描述不符。
参考链接:
相关推荐
C++ 对象内存模型 C++ 对象内存模型是 C++ 编程语言中一个重要的概念, 它描述了 C++ 对象在内存中的存储结构。这个模型是 C++ 编程语言的基础之一,对于理解 C++ 编程语言的工作机理具有重要的意义。 在 C++ 中,...
这本书的目标是帮助读者理解C++对象模型背后的细节,包括内存管理、类型系统、对象生命周期、继承、多态等核心概念。 C++对象模型是C++编程的基础,它描述了如何在内存中表示类和对象,以及它们之间的关系。首先,...
C++对象模型是C++编程语言中一个核心且复杂的概念,它定义了如何在内存中表示类、对象以及它们之间的关系。理解C++对象模型对于深入掌握C++语言特性、优化代码性能以及进行高效内存管理至关重要。 #### 对象模型的...
C++对象模型是C++编程的基础,它涉及到内存布局、虚函数、多态性、继承和封装等多个方面。首先,书中会详细讲解C++对象在内存中的表示方式,包括对象头、成员变量和成员函数的存储位置。理解这一部分对于优化内存...
C++对象内存布局 C++对象内存布局是指在C++编程语言中对象在内存中的存储结构和布局方式。了解C++对象的内存布局对于理解C++编程语言的对象模型和内存管理机制非常重要。 从内存布局的角度来看,C++对象可以分为三...
《深度探索C++对象模型》是侯捷翻译的一本关于C++对象模型深入探讨的专业书籍,原著作者为Stanley B. Lippman。这本书详细解析了C++中对象的内部表示、构造和析构的过程以及运行时行为等关键概念。它不仅仅是一本...
《深度探索C++对象模型》是一本面向有C语言基础的读者,旨在深入解析C++这一强大编程语言中关于对象模型的专著。C++作为面向对象编程的典范,其对象模型是理解语言特性和底层机制的关键。这本书的中文清晰版提供了一...
C++对象模型是C++语言的核心,它涉及到内存管理、类结构、对象生命周期、继承、多态等关键概念。在《Inside The C++ Object Model》这本书中,作者深入浅出地解析了这些概念,让读者能了解C++编译器如何将源代码转化...
在探索C++对象模型之前,首先需要理解对象模型(Object Model)的含义。对象模型是面向对象编程(Object-Oriented Programming,OOP)中的一个核心概念,它描述了对象的结构、属性、方法、以及对象之间的关系。C++...
在实际编程中,理解C++对象模型有助于优化内存使用,避免内存泄漏,提升程序性能,以及更好地设计和实现复杂系统。例如,通过理解对象的内存布局,可以更有效地使用内存对齐,减少访问时间;通过理解虚函数表,可以...
C++的类继承内存布局是理解C++对象模型的基础。在单继承情况下,派生类对象会包含基类的成员变量和成员函数,这就像是在基类的基础上不断添加新的功能。然而,当涉及到多重继承,特别是当多个基类包含同名成员时,...
《深度探索C++对象模型》是一本专注于C++编程语言底层机制的专业书籍,它揭示了C++对象在内存中的表示方式以及对象模型的工作原理。这本书是面向已经对C++有一定基础理解的开发者,旨在帮助他们深入理解C++的内部...
1. **C++对象模型**:C++对象模型是C++编程的基础,它描述了在C++程序中类和对象是如何在内存中存储和交互的。对象模型包括对象的生命周期、成员变量的布局、虚函数表、构造与析构过程、静态成员等内容。理解这一...
《深度探索C++对象模型》这本书,由Stanley B. Lippman撰写,侯捷翻译,由华中科技大学出版社出版。本书致力于深入解析C++编译器在处理C++代码时所采取的复杂对象模型及其背后的底层机制,特别是针对构造函数、解构...
C++对象模型是C++语言的基础,它涉及到类、对象、继承、多态、内存管理等核心概念的实现细节。这本书的中英文版本为读者提供了丰富的学习资源,无论你是初级程序员还是经验丰富的开发者,都能从中获益匪浅。 1. **...
深度探索C++对象模型是理解C++编程核心概念的关键。C++是一种混合了过程化编程和面向对象编程的编程语言,它的对象模型是其强大功能的基础。在C++中,对象是类的实例,类定义了一组数据成员和成员函数,这些成员函数...
了解C++对象内存布局的额外问题,比如C++封装带来的布局成本有多大?对于一个由空类组成的继承层次中,每个类对象的大小是多少?这些问题的答案取决于编译器的具体实现和内存对齐的规则。C++编译器通常需要为每个类...