Avoiding vtable pointers in objects in C++

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
0
down vote

favorite
1












In my previous question, it was highlight that implementations of C++ such as GCC must store a vtable pointer in every copy of a class for each parent class which has a virtual function.



So a class which implements say 5 "interfaces" (i.e. pure abstract classes) must be at least 5 pointers in size before even it's own members are added.



At first glance, this seems necessary. When we upcast, all we can do is change the pointer. But we need a new vtable for that upcasted pointer. So there's not much option other than putting it in the object itself.



The downside of this is that we pay a per-object cost for virtual parent classes, even ones with no members.



How about instead, making a pointer "two pointers". The first pointer is a pointer to the object. The second is a pointer to it's vtable. This could perhaps only be done for virtual objects.



The object itself could now just be pure data, no need for vtable pointers.



Note then we only need one vtable pointer, even if there's multiple parents. The vtable itself could have entries describing how to upcast, or perhaps the compiler just knows how to do this.



Is there any reason this approach is not viable> Are there any C++ implementations that do this?



(Note: I understand one can avoid pure abstract bases as interfaces and "duck typing" and in the future concepts but lets ignore that for the moment)







share|improve this question



















  • In practice it does not matter: multiple inheritance is rarely used, and in the few cases it is used the object is usually quite "big" -data fields are also inherited- (and the multiple superclasses are few, more often 2 than 5).
    – Basile Starynkevitch
    Aug 6 at 13:36

















up vote
0
down vote

favorite
1












In my previous question, it was highlight that implementations of C++ such as GCC must store a vtable pointer in every copy of a class for each parent class which has a virtual function.



So a class which implements say 5 "interfaces" (i.e. pure abstract classes) must be at least 5 pointers in size before even it's own members are added.



At first glance, this seems necessary. When we upcast, all we can do is change the pointer. But we need a new vtable for that upcasted pointer. So there's not much option other than putting it in the object itself.



The downside of this is that we pay a per-object cost for virtual parent classes, even ones with no members.



How about instead, making a pointer "two pointers". The first pointer is a pointer to the object. The second is a pointer to it's vtable. This could perhaps only be done for virtual objects.



The object itself could now just be pure data, no need for vtable pointers.



Note then we only need one vtable pointer, even if there's multiple parents. The vtable itself could have entries describing how to upcast, or perhaps the compiler just knows how to do this.



Is there any reason this approach is not viable> Are there any C++ implementations that do this?



(Note: I understand one can avoid pure abstract bases as interfaces and "duck typing" and in the future concepts but lets ignore that for the moment)







share|improve this question



















  • In practice it does not matter: multiple inheritance is rarely used, and in the few cases it is used the object is usually quite "big" -data fields are also inherited- (and the multiple superclasses are few, more often 2 than 5).
    – Basile Starynkevitch
    Aug 6 at 13:36













up vote
0
down vote

favorite
1









up vote
0
down vote

favorite
1






1





In my previous question, it was highlight that implementations of C++ such as GCC must store a vtable pointer in every copy of a class for each parent class which has a virtual function.



So a class which implements say 5 "interfaces" (i.e. pure abstract classes) must be at least 5 pointers in size before even it's own members are added.



At first glance, this seems necessary. When we upcast, all we can do is change the pointer. But we need a new vtable for that upcasted pointer. So there's not much option other than putting it in the object itself.



The downside of this is that we pay a per-object cost for virtual parent classes, even ones with no members.



How about instead, making a pointer "two pointers". The first pointer is a pointer to the object. The second is a pointer to it's vtable. This could perhaps only be done for virtual objects.



The object itself could now just be pure data, no need for vtable pointers.



Note then we only need one vtable pointer, even if there's multiple parents. The vtable itself could have entries describing how to upcast, or perhaps the compiler just knows how to do this.



Is there any reason this approach is not viable> Are there any C++ implementations that do this?



(Note: I understand one can avoid pure abstract bases as interfaces and "duck typing" and in the future concepts but lets ignore that for the moment)







share|improve this question











In my previous question, it was highlight that implementations of C++ such as GCC must store a vtable pointer in every copy of a class for each parent class which has a virtual function.



So a class which implements say 5 "interfaces" (i.e. pure abstract classes) must be at least 5 pointers in size before even it's own members are added.



At first glance, this seems necessary. When we upcast, all we can do is change the pointer. But we need a new vtable for that upcasted pointer. So there's not much option other than putting it in the object itself.



The downside of this is that we pay a per-object cost for virtual parent classes, even ones with no members.



How about instead, making a pointer "two pointers". The first pointer is a pointer to the object. The second is a pointer to it's vtable. This could perhaps only be done for virtual objects.



The object itself could now just be pure data, no need for vtable pointers.



Note then we only need one vtable pointer, even if there's multiple parents. The vtable itself could have entries describing how to upcast, or perhaps the compiler just knows how to do this.



Is there any reason this approach is not viable> Are there any C++ implementations that do this?



(Note: I understand one can avoid pure abstract bases as interfaces and "duck typing" and in the future concepts but lets ignore that for the moment)









share|improve this question










share|improve this question




share|improve this question









asked Aug 6 at 4:08









Clinton

5891610




5891610











  • In practice it does not matter: multiple inheritance is rarely used, and in the few cases it is used the object is usually quite "big" -data fields are also inherited- (and the multiple superclasses are few, more often 2 than 5).
    – Basile Starynkevitch
    Aug 6 at 13:36

















  • In practice it does not matter: multiple inheritance is rarely used, and in the few cases it is used the object is usually quite "big" -data fields are also inherited- (and the multiple superclasses are few, more often 2 than 5).
    – Basile Starynkevitch
    Aug 6 at 13:36
















In practice it does not matter: multiple inheritance is rarely used, and in the few cases it is used the object is usually quite "big" -data fields are also inherited- (and the multiple superclasses are few, more often 2 than 5).
– Basile Starynkevitch
Aug 6 at 13:36





In practice it does not matter: multiple inheritance is rarely used, and in the few cases it is used the object is usually quite "big" -data fields are also inherited- (and the multiple superclasses are few, more often 2 than 5).
– Basile Starynkevitch
Aug 6 at 13:36











2 Answers
2






active

oldest

votes

















up vote
6
down vote














How about instead, making a pointer "two pointers".




This would bloat every pointer, even those which don't use dynamic polymorphism. Remember: you have to be able to cast any object pointer to void* and back to that type with valid behavior. That wouldn't be possible unless every pointer used your "two pointer" approach. Plus, the C++ standard does not permit the size of an object pointer to be determined by what type it points to.



This would also break ABI with C and every C API function ever written. C++ implementations like to be able to call C APIs.



C++ is a language that prefers to follow the "don't pay for what you don't use" rule. Users who use lots of multiple inheritance of virtual interfaces pay for it; users who don't use these things don't have to pay anything. That is as it should be.






share|improve this answer






























    up vote
    4
    down vote














    How about instead, making a pointer "two pointers".




    Yes, I think that could be done, theoretically — there are a lot of ways C++ could be implemented. These choices are all trade-offs of one thing for another; though, there are lots of considerations to be made in such an implementation.



    C++ avoids search across multiple inheritance parent classes by capitalizing on the point of conversion (from the concrete class to the (abstract) base). Other languages choose instead to search for an interface in the vtable of the concrete class (and instead do nothing at point of conversion), but pretty sure C++ could do that, too, if they wanted to, don't think there's any strict rule as to how it must be implemented.  (FYI, Doing nothing at point of conversion tends to be somewhat friendlier to garbage collection, another reason this tends to be favored by C# and Java.)



    However, C++ allows instance fields in (abstract) base classes, whereas C# and Java don't support instance fields for interfaces.  This makes things a bit trickier for C++, since it has to know about data slots in the object as well as function slots in the vtable.  Perhaps due to this, I think, C++'s usually settle on adjusting the object pointer at point of conversion, rather than searching for data slots and searching for virtual function slots.



    Note that a single object implementing 5 different interfaces is, IMHO, overrated.  You might find composition better for many scenarios, meaning that you would create several cooperating classes, each class implementing only one interface.



    (Also note that the overhead you're describing only happens on the second parent class, not the first, as the subclass and its first base can share a vtable pointer.)



    In any case, the overhead is minimal unless you're going to create a huge amount of these objects.  Usually, objects created in great quantities can be optimized in various ways, such as the (albeit complex) flyweight pattern.






    share|improve this answer























      Your Answer







      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "131"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      convertImagesToLinks: false,
      noModals: false,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );








       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f376441%2favoiding-vtable-pointers-in-objects-in-c%23new-answer', 'question_page');

      );

      Post as a guest






























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      6
      down vote














      How about instead, making a pointer "two pointers".




      This would bloat every pointer, even those which don't use dynamic polymorphism. Remember: you have to be able to cast any object pointer to void* and back to that type with valid behavior. That wouldn't be possible unless every pointer used your "two pointer" approach. Plus, the C++ standard does not permit the size of an object pointer to be determined by what type it points to.



      This would also break ABI with C and every C API function ever written. C++ implementations like to be able to call C APIs.



      C++ is a language that prefers to follow the "don't pay for what you don't use" rule. Users who use lots of multiple inheritance of virtual interfaces pay for it; users who don't use these things don't have to pay anything. That is as it should be.






      share|improve this answer



























        up vote
        6
        down vote














        How about instead, making a pointer "two pointers".




        This would bloat every pointer, even those which don't use dynamic polymorphism. Remember: you have to be able to cast any object pointer to void* and back to that type with valid behavior. That wouldn't be possible unless every pointer used your "two pointer" approach. Plus, the C++ standard does not permit the size of an object pointer to be determined by what type it points to.



        This would also break ABI with C and every C API function ever written. C++ implementations like to be able to call C APIs.



        C++ is a language that prefers to follow the "don't pay for what you don't use" rule. Users who use lots of multiple inheritance of virtual interfaces pay for it; users who don't use these things don't have to pay anything. That is as it should be.






        share|improve this answer

























          up vote
          6
          down vote










          up vote
          6
          down vote










          How about instead, making a pointer "two pointers".




          This would bloat every pointer, even those which don't use dynamic polymorphism. Remember: you have to be able to cast any object pointer to void* and back to that type with valid behavior. That wouldn't be possible unless every pointer used your "two pointer" approach. Plus, the C++ standard does not permit the size of an object pointer to be determined by what type it points to.



          This would also break ABI with C and every C API function ever written. C++ implementations like to be able to call C APIs.



          C++ is a language that prefers to follow the "don't pay for what you don't use" rule. Users who use lots of multiple inheritance of virtual interfaces pay for it; users who don't use these things don't have to pay anything. That is as it should be.






          share|improve this answer
















          How about instead, making a pointer "two pointers".




          This would bloat every pointer, even those which don't use dynamic polymorphism. Remember: you have to be able to cast any object pointer to void* and back to that type with valid behavior. That wouldn't be possible unless every pointer used your "two pointer" approach. Plus, the C++ standard does not permit the size of an object pointer to be determined by what type it points to.



          This would also break ABI with C and every C API function ever written. C++ implementations like to be able to call C APIs.



          C++ is a language that prefers to follow the "don't pay for what you don't use" rule. Users who use lots of multiple inheritance of virtual interfaces pay for it; users who don't use these things don't have to pay anything. That is as it should be.







          share|improve this answer















          share|improve this answer



          share|improve this answer








          edited Aug 6 at 13:14


























          answered Aug 6 at 4:30









          Nicol Bolas

          8,71532733




          8,71532733






















              up vote
              4
              down vote














              How about instead, making a pointer "two pointers".




              Yes, I think that could be done, theoretically — there are a lot of ways C++ could be implemented. These choices are all trade-offs of one thing for another; though, there are lots of considerations to be made in such an implementation.



              C++ avoids search across multiple inheritance parent classes by capitalizing on the point of conversion (from the concrete class to the (abstract) base). Other languages choose instead to search for an interface in the vtable of the concrete class (and instead do nothing at point of conversion), but pretty sure C++ could do that, too, if they wanted to, don't think there's any strict rule as to how it must be implemented.  (FYI, Doing nothing at point of conversion tends to be somewhat friendlier to garbage collection, another reason this tends to be favored by C# and Java.)



              However, C++ allows instance fields in (abstract) base classes, whereas C# and Java don't support instance fields for interfaces.  This makes things a bit trickier for C++, since it has to know about data slots in the object as well as function slots in the vtable.  Perhaps due to this, I think, C++'s usually settle on adjusting the object pointer at point of conversion, rather than searching for data slots and searching for virtual function slots.



              Note that a single object implementing 5 different interfaces is, IMHO, overrated.  You might find composition better for many scenarios, meaning that you would create several cooperating classes, each class implementing only one interface.



              (Also note that the overhead you're describing only happens on the second parent class, not the first, as the subclass and its first base can share a vtable pointer.)



              In any case, the overhead is minimal unless you're going to create a huge amount of these objects.  Usually, objects created in great quantities can be optimized in various ways, such as the (albeit complex) flyweight pattern.






              share|improve this answer



























                up vote
                4
                down vote














                How about instead, making a pointer "two pointers".




                Yes, I think that could be done, theoretically — there are a lot of ways C++ could be implemented. These choices are all trade-offs of one thing for another; though, there are lots of considerations to be made in such an implementation.



                C++ avoids search across multiple inheritance parent classes by capitalizing on the point of conversion (from the concrete class to the (abstract) base). Other languages choose instead to search for an interface in the vtable of the concrete class (and instead do nothing at point of conversion), but pretty sure C++ could do that, too, if they wanted to, don't think there's any strict rule as to how it must be implemented.  (FYI, Doing nothing at point of conversion tends to be somewhat friendlier to garbage collection, another reason this tends to be favored by C# and Java.)



                However, C++ allows instance fields in (abstract) base classes, whereas C# and Java don't support instance fields for interfaces.  This makes things a bit trickier for C++, since it has to know about data slots in the object as well as function slots in the vtable.  Perhaps due to this, I think, C++'s usually settle on adjusting the object pointer at point of conversion, rather than searching for data slots and searching for virtual function slots.



                Note that a single object implementing 5 different interfaces is, IMHO, overrated.  You might find composition better for many scenarios, meaning that you would create several cooperating classes, each class implementing only one interface.



                (Also note that the overhead you're describing only happens on the second parent class, not the first, as the subclass and its first base can share a vtable pointer.)



                In any case, the overhead is minimal unless you're going to create a huge amount of these objects.  Usually, objects created in great quantities can be optimized in various ways, such as the (albeit complex) flyweight pattern.






                share|improve this answer

























                  up vote
                  4
                  down vote










                  up vote
                  4
                  down vote










                  How about instead, making a pointer "two pointers".




                  Yes, I think that could be done, theoretically — there are a lot of ways C++ could be implemented. These choices are all trade-offs of one thing for another; though, there are lots of considerations to be made in such an implementation.



                  C++ avoids search across multiple inheritance parent classes by capitalizing on the point of conversion (from the concrete class to the (abstract) base). Other languages choose instead to search for an interface in the vtable of the concrete class (and instead do nothing at point of conversion), but pretty sure C++ could do that, too, if they wanted to, don't think there's any strict rule as to how it must be implemented.  (FYI, Doing nothing at point of conversion tends to be somewhat friendlier to garbage collection, another reason this tends to be favored by C# and Java.)



                  However, C++ allows instance fields in (abstract) base classes, whereas C# and Java don't support instance fields for interfaces.  This makes things a bit trickier for C++, since it has to know about data slots in the object as well as function slots in the vtable.  Perhaps due to this, I think, C++'s usually settle on adjusting the object pointer at point of conversion, rather than searching for data slots and searching for virtual function slots.



                  Note that a single object implementing 5 different interfaces is, IMHO, overrated.  You might find composition better for many scenarios, meaning that you would create several cooperating classes, each class implementing only one interface.



                  (Also note that the overhead you're describing only happens on the second parent class, not the first, as the subclass and its first base can share a vtable pointer.)



                  In any case, the overhead is minimal unless you're going to create a huge amount of these objects.  Usually, objects created in great quantities can be optimized in various ways, such as the (albeit complex) flyweight pattern.






                  share|improve this answer
















                  How about instead, making a pointer "two pointers".




                  Yes, I think that could be done, theoretically — there are a lot of ways C++ could be implemented. These choices are all trade-offs of one thing for another; though, there are lots of considerations to be made in such an implementation.



                  C++ avoids search across multiple inheritance parent classes by capitalizing on the point of conversion (from the concrete class to the (abstract) base). Other languages choose instead to search for an interface in the vtable of the concrete class (and instead do nothing at point of conversion), but pretty sure C++ could do that, too, if they wanted to, don't think there's any strict rule as to how it must be implemented.  (FYI, Doing nothing at point of conversion tends to be somewhat friendlier to garbage collection, another reason this tends to be favored by C# and Java.)



                  However, C++ allows instance fields in (abstract) base classes, whereas C# and Java don't support instance fields for interfaces.  This makes things a bit trickier for C++, since it has to know about data slots in the object as well as function slots in the vtable.  Perhaps due to this, I think, C++'s usually settle on adjusting the object pointer at point of conversion, rather than searching for data slots and searching for virtual function slots.



                  Note that a single object implementing 5 different interfaces is, IMHO, overrated.  You might find composition better for many scenarios, meaning that you would create several cooperating classes, each class implementing only one interface.



                  (Also note that the overhead you're describing only happens on the second parent class, not the first, as the subclass and its first base can share a vtable pointer.)



                  In any case, the overhead is minimal unless you're going to create a huge amount of these objects.  Usually, objects created in great quantities can be optimized in various ways, such as the (albeit complex) flyweight pattern.







                  share|improve this answer















                  share|improve this answer



                  share|improve this answer








                  edited Aug 6 at 13:44


























                  answered Aug 6 at 4:53









                  Erik Eidt

                  19.9k32949




                  19.9k32949






















                       

                      draft saved


                      draft discarded


























                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f376441%2favoiding-vtable-pointers-in-objects-in-c%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      Comments

                      Popular posts from this blog

                      What is the equation of a 3D cone with generalised tilt?

                      Color the edges and diagonals of a regular polygon

                      Relationship between determinant of matrix and determinant of adjoint?