|
-
June 10th, 2006, 11:38 PM
#1
How do i avoid those nasty vtable?
Vtables, those nasty memory block that makes each class 4 bytes bigger when it uses virtuals. There is a way to avoid them, and your compiler may even optimize it for a very little tiny bit more speed(if it optimizes virtuals diffrent than normal functions at all).
This could perhaps make pc's work faster, for each class instance it doesnt need to construct a vtable anymore, and doesnt need as much ram anymore. There could be alot of classes used with vtables in all of your applications on your pc.
Imagine a game that uses objects with vtables. It has initialized 1 000 objects and there are 3 create and 3 destroyed evry second thats up 4 000 bytes to much allocated space! and 12 bytes allocated evry second for nothing.
This can easily be accomplished by a "container" structure.
Here is a basic example:
Code:
#include <cstdio>
template<typename t_Container = Animal>
struct Animal
{
struct ACTIONS
{
static void Talk(const Animal& me)
{
me.Say("...");
}
};
void Say(const char* text) const
{
printf("%s", text);
}
void Talk(void) const
{
t_Container::ACTIONS::Talk(*this);
}
};
struct Cow: Animal<Cow>
{
struct ACTIONS: Animal::ACTIONS
{
static void Talk(const Animal& me)
{
me.Say("mooo");
}
};
};
int main(void)
{
Cow MyPet;
printf("%s", "My pet says: ");
MyPet.Talk();
while(true);
return(0);
}
Downside:
Yes there is a downside. In my code above, there is this rule: Once a cow always a cow. It cannot say ... anymore, like an animal without race would say.
results:
sizeof(Cow) returned 1, sizeof(CowV) (same class but using a virtual function) returned 4, conclusion my idea worked.
This method is VERY usefull as i stated ealier. But has its downside, but most of the time the downside shulndt be much of a big deal.
Last edited by Mitsukai; June 10th, 2006 at 11:57 PM.
-
June 11th, 2006, 12:47 AM
#2
Re: How do i avoid those nasty vtable?
 Originally Posted by Mitsukai
This method is VERY usefull as i stated ealier. But has its downside, but most of the time the downside shulndt be much of a big deal.
No, the downside *is* a big deal.
Actually, your class it is not runtime-polymorphic at all.
Since the base class contains the derived class as template parameter, it is even much more useless, than normal inheritance without virtual functions.
So, it is not better than function hiding:
Code:
#include <iostream>
struct Animal
{
void Talk() {Say("(I'm an animal)");}
void Say(const char* text) {std::cout << text;}
};
struct Cow:public Animal
{
void Talk()
{
Say("mooo");
}
};
int main() {
Cow cow;
Animal* p=&cow;
p->Talk(); // it calls the base class method
// but at least the LSP principle works a bit (you can have an Animal* pointing to a cow).
cow.Talk(); // it calls the derived class method
}
With this (old-style) class hierarchy, you can at last add new classes derived from Animal.
But with your strangely recurring template pattern, you can't add derived classes... All these derived classes : Animal<Cow>, Animal<AnyOther> have *different* base classes.
Which, basically (except very special cases) kills the whole point of inheritance.
However, if you really have to gain 4 bytes, you can write your own vtable system, using only 1 or 2 bytes which would be an index in a static-storage table of vtable pointers.
It adds a level of indirection, and limits the total number of vtable (256 or 65536), but reduces the space loss.
You can also use "#pragma pack(1)" or an equivalent directive.
This method is VERY usefull as i stated ealier
Give me one real life example where it works better than a simple class hierarchy without virtual functions.
"inherit to be reused by code that uses the base class, not to reuse base class code", Sutter and Alexandrescu, C++ Coding Standards.
Club of lovers of the C++ typecasts cute syntax: Only recorded member.
Out of memory happens! Handle it properly!
Say no to g_new()!
-
June 11th, 2006, 07:31 PM
#3
Re: How do i avoid those nasty vtable?
 Originally Posted by Mitsukai
Imagine a game that uses objects with vtables. It has initialized 1 000 objects and there are 3 create and 3 destroyed evry second thats up 4 000 bytes to much allocated space! and 12 bytes allocated evry second for nothing.
Big deal! A whole FOUR THOUSAND bytes! A whole TWELVE bytes every second!
Just think of the programmer time wasted worrying about a whole TWELVE bytes a second! I mean, at that rate I'd have to wait 2.8 YEARS until my computer ran out of memory. Oh! My! God! My! Computer! Might! Run! Out! Of! Memory! In! Nearly! Three! Years!
Sorry, but I seriously think you're finding non-optimisations for non-problems again. Afterall, you use just as much memory having a pointer to the object as your do for the vtable for the object.
And before you say "Well, if everyone optimised like this computers would run SOOOOOO much faster"... I'd point out that my 1GB RAM machine runnin winXP under rather demanding conditions doesn't hit the memory limit. Unless you have a convincing cache-oriented argument, using more memory doesn't mean slowness.
In a simular vein, if you're coding for embedded systems and 4 bytes per object is an issue, then you wouldn't be using C++ or even C for development. Using hand-hacked assembler you could reduce the code size and reduce the data structure size to it's absolute minimum. No other abstraction level allows that. You probably wouldn't be using dynamic memory allocation at all since that generally requires at least EIGHT bytes per object for maintaining the heap data structure! OH! NO! NOT! EIGHT! BYTES! PER! DYNAMICALLY! ALLOCATED! OBJECT! And you thought an extra FOUR bytes for the vtable was bad!
(My apologies for the degree of sarcasm... it's not been the best of days. Admittedly, it's not /that/ sarcastic either.)
Last edited by Noddon; June 11th, 2006 at 07:56 PM.
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. - Brian W. Kernighan
-
June 11th, 2006, 08:20 PM
#4
Re: How do i avoid those nasty vtable?
Originally Posted by Mitsukai
Imagine a game that uses objects with vtables. It has initialized 1 000 objects and there are 3 create and 3 destroyed evry second thats up 4 000 bytes to much allocated space! and 12 bytes allocated evry second for nothing.
If you writing code for embedded devices with small memory footprint, it does matters. In such cases, you should be using C instead of C++. However, if you need to achieve polymorphism in C, you still need to write almost the same code to implement vtable which the C++ compiler usually do a better job than us.
quoted from C++ Coding Standards:
KISS (Keep It Simple Software):
Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
Avoid magic number:
Programming isn't magic, so don't incant it.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|