1

When using wrapper classes in C++, like

class myInt {
  int _value;
public:
  myInt( int value ) : _value( value );
  int value() const { return _value; }

}

, is there any memory overhead compared to a simple int?

This answer says "not if there's no virtual functions", but I want to understand the exact reason.

I looked into § 10.3 [class.virtual] of ISO/IEC 14882:2003, which say: "A class that declares or inherits a virtual function is called a polymorphic class." I understand that objects of such a class do not need to have a vtable pointer in them.

But I don't understand how it follows from this that it does not have to have any memory overhead. I can create a class deriving from myInt, calling it, say, myDerivedInt. Can't I do a dynamic_cast from a myInt * to a myDerivedInt *? If not, why not?

Community
  • 1
  • 1
Jens Müller
  • 302
  • 4
  • 13
  • You can check if there's memory overhead by comparing `sizeof(int)` and `sizeof(myInt)`. – Kerrek SB Aug 10 '14 at 14:52
  • I could add that to my unit tests :-) – Jens Müller Aug 10 '14 at 15:03
  • I think a static assertion might be a more appropriate way to ensure this, since it's a platform-dependent property of your code that won't be affected by code changes (unless you change the class layout). – Kerrek SB Aug 10 '14 at 15:05

3 Answers3

2

Is there any memory overhead compared to a simple €int`?

I would say not, but I don't know if it is guaranteed.

I understand that objects of such a class do not need to have a vtable pointer in them.

If the polymorphic class object is created on the stack, and its address is never taken, the compiler might figure out that its functions are never called virtually (dynamic-dispatch) and could remove the virtual table pointer from the stack. (This applies only on a per-case basis. Instances of the class in other places may include the vtable pointer). This kind of optimization would have very small impact, so I wouldn't worry about if it does or not. In general, a class which inherits from a class with a vtable, will also have a vtable pointer in its instances.

Can't I do a dynamic_cast from a myInt* to a myDerivedInt*?

No. Not if it doesn't have a vtable. In other words, if myInt doesn't have any virtual functions (or doesn't inherit from any class that does), then you cannot dynamic_cast from MyInt* to MyDerivedInt*. You can use static_cast, however.

If not, why not?

Because there is no vtable in myInt. The vtable stores the information needed for dynamic_cast.

David G
  • 94,763
  • 41
  • 167
  • 253
Neil Kirk
  • 21,327
  • 9
  • 53
  • 91
  • Thanks. Actually, vtable is a term not used in the standard, so it's hard to find the explanation there when you look for that term. Rather, the standard defines it the other way round: It says if a class does not have virtual functions, it's non-polymorphic. And if it's non-polymorphic, you're not allowed to dynamic_cast down from it. And from BOTH rules (function class not using virtual dispatch, dynamic_cast not possible), compiler implementers can deduce that a vtable is not necessary for non-polymorphic classes. – Jens Müller Aug 10 '14 at 15:02
  • @JensMüller The standard does not mention vtables because that's an implementation detail. Technically, compilers *could* implement virtual function calls in some other way that did not rely on a virtual table and a vtable pointer, but as far as I know, all compilers use vtables because that's the best way to do it. The `dynamic_cast` requires a virtual call, and that's why the compiler requires it only if it would not add additional (per *object*) overhead, i.e., if there are already virtual functions, dyn-cast support just adds an entry to the vtable (per *class*). – Mikael Persson Aug 10 '14 at 16:56
1

But I don't understand how it follows from this that it does not have to have any memory overhead

Well, the only reason why memory overhead would be required is if something else has to be stored in the class. It has to contain an int, obviously, because that's its member. But it doesn't need a vtable pointer, and nothing else in the C++ standard mandates that anything else must be contained in the class. The class can be implemented without memory overhead not because the C++ standard says "this can be done with no memory overhead", but because it doesn't say "in addition to the int member, the class must also contain ". It doesn't specify anything that would require overhead to be introduced, so because of that, the overhead can be avoided.

And of course, when compilers can avoid additional overhead, they typically do so, so in practice such a class will have no memory overhead.

jalf
  • 243,077
  • 51
  • 345
  • 550
0

OK, while writing this and finishing the last sentence, I found the answer:

Clause 6 of § 5.2.7 [expr.dynamic.cast] says:

Otherwise, v shall be a pointer to or an lvalue of a polymorphic type (10.3).

I had actually looked "polymorphic type" in the index, but that only mentioned the occurence in 10.3 ...

Jens Müller
  • 302
  • 4
  • 13