包装类的内存开销 使用C++中的包装类,如 class myInt { int _value; public: myInt( int value ) : _value( value ); int value() const { return _value; } }

包装类的内存开销 使用C++中的包装类,如 class myInt { int _value; public: myInt( int value ) : _value( value ); int value() const { return _value; } },c++,memory-management,wrapper,C++,Memory Management,Wrapper,,与简单int相比,是否有内存开销 说“如果没有虚拟函数就不会”,但我想知道确切的原因 我研究了ISO/IEC 14882:2003的§10.3[class.virtual],其中说:“声明或继承虚拟函数的类称为多态类。”我理解此类对象不需要在其中包含vtable指针 但是我不明白为什么它不需要任何内存开销。我可以创建一个从myInt派生的类,称之为myDerivedInt。我不能从myInt*到myDerivedInt*进行动态转换吗?如果没有,为什么不呢?好的,在写这篇文章并完成最后一句时,

,与简单int相比,是否有内存开销

说“如果没有虚拟函数就不会”,但我想知道确切的原因

我研究了ISO/IEC 14882:2003的§10.3[class.virtual],其中说:“声明或继承虚拟函数的类称为多态类。”我理解此类对象不需要在其中包含vtable指针


但是我不明白为什么它不需要任何内存开销。我可以创建一个从myInt派生的类,称之为myDerivedInt。我不能从myInt*到myDerivedInt*进行动态转换吗?如果没有,为什么不呢?

好的,在写这篇文章并完成最后一句时,我找到了答案:

§5.2.7[解释动态演员表]第6条规定:

否则,v应为多态类型(10.3)的指针或左值

实际上,我在索引中查看了“多态类型”,但这只提到了10.3中的出现

与一个简单的''''.'整型'''相比,有没有内存开销

我想说没有,但我不知道是否有保证

我理解这样一个类的对象不需要有一个vtable指针

如果多态类对象是在堆栈上创建的,并且其地址从未被获取,编译器可能会发现其函数从未被虚拟调用(动态调度),并且可能会从堆栈中删除虚拟表指针。(这仅适用于每种情况。其他位置的类实例可能包括vtable指针)。这种优化会产生非常小的影响,所以我不会担心它是否会产生影响。通常,从具有vtable的类继承的类在其实例中也将具有vtable指针

我不能从
myInt*
myDerivedInt*
进行
动态转换吗

不,如果它没有vtable就不会。换句话说,如果
myInt
没有任何虚拟函数(或者没有从任何有虚拟函数的类继承),那么就不能将
dynamic\u cast
myInt*
转换为
MyDerivedInt*
。但是,您可以使用
static\u cast

若否,原因为何

因为
myInt
中没有vtable。vtable存储
动态\u cast
所需的信息

但是我不明白为什么它不需要任何内存开销

嗯,需要内存开销的唯一原因是如果类中必须存储其他内容。显然,它必须包含一个
int
,因为这是它的成员。但它不需要VTABLE指针,C++标准中没有任何其他命令要求在该类中包含任何其他内容。该类可以在没有内存开销的情况下实现,这不是因为C++标准说“这可以在没有内存开销的情况下完成”,而是因为它没有说“除了<代码> int <代码>成员之外,类还必须包含”。它没有指定任何需要引入开销的内容,因此可以避免开销


当然,当编译器可以避免额外的开销时,它们通常会这样做,因此实际上这样的类不会有内存开销。

您可以通过比较
sizeof(int)
sizeof(myInt)来检查是否有内存开销
。我可以将其添加到我的单元测试中:-)我认为静态断言可能是确保这一点的更合适的方法,因为它是代码的平台相关属性,不会受到代码更改的影响(除非更改类布局)。谢谢。实际上,vtable是标准中未使用的术语,因此在查找该术语时很难找到解释。相反,标准对它的定义是相反的:它说如果一个类没有虚函数,那么它是非多态的。如果它是非多态的,你就不允许从它身上扔下。从这两个规则(函数类不使用虚拟分派,动态强制转换不可能),编译器实现者可以推断vtable对于非多态类是不必要的。@JensMüller标准没有提到vtables,因为这是一个实现细节。从技术上讲,编译器可以通过其他方式实现虚拟函数调用,而不依赖于虚拟表和vtable指针,但据我所知,所有编译器都使用vtables,因为这是最好的方法。
dynamic_cast
需要一个虚拟调用,这就是为什么编译器只有在不增加额外(每个对象)开销的情况下才需要它,也就是说,如果已经有虚拟函数,dyn cast支持只会向vtable(每个类)添加一个条目。