Size of C++ polymorphic objects.

Started by
12 comments, last by Zorinthrox 5 years, 10 months ago

I already asked this question on stack overflow, and they got pissed at me, down-voted me and so forth, LOL .... so I'm pretty sure the answer is NO, but I'll try again here anyway just in case..... Is there any way to get the size of a polymorphic object at run-time? I know you can create a virtual function that returns size and overload it for each child class, but I'm trying to avoid that since (a) it takes a virtual function call and I want it to be fast and (b) it's a pain to have to include the size function for every subclass. I figure since each object has a v-table their should be some way since the information is there, but perhaps there is no portable way to do it.

Advertisement

If by "polymorphic object", you mean "derived type but using a base type pointer", then no, of course you can't get that without virtual function dispatch or a dynamic_cast.  C++ has no way of knowing which type you actually want the size of, even with RTTI.  Therefore, you either have to tell it, either directly (through dynamic_cast), or indirectly (through providing the plumbing in the virtual interface).

I mean an instantiated object of a class with a virtual function..... A common case which I imagine could be implemented without too many problems is simply some operator/function that returns the size of the full object in memory.   Seems like they are mucking with the language all the time so I was hoping there was some new way to do it but I guess not.

5 minutes ago, Gnollrunner said:

Seems like they are mucking with the language all the time so I was hoping there was some new way to do it but I guess not.

C++ pseudo-operator sizeof works at compile time, not at runtime, so it unable to determine size of object that exact type is unknown at compile time. So only way  to get size of object at runtime is a virtual method.

9 hours ago, Gnollrunner said:

I already asked this question on stack overflow, and they got pissed at me, down-voted me and so forth, LOL ....

it really "must know after first lecture" question about C and C++ 

#define if(a) if((a) && rand()%100)

9 hours ago, Gnollrunner said:

 I figure since each object has a v-table their should be some way since the information is there, but perhaps there is no portable way to do it.

Each polymorphic object with have a vtable, but at runtime the code wont know anything about it other than that the vtable is there and where to go get those functions.  That's how it works, it just calls whatever is in the vtable for each function.  So while the knowledge about the object type is there during compile, it doesnt get added to objects such that it can be accessed during runtime.  

This is such an odd question, I feel like it must be you having a different problem, thinking of (but not really) having the solution which you "just" need the size of the objects for. If you need to ask a polymorphic object which type it is, you are most likely on the wrong way. Also I imagine you wanting the size to copy around the objects manually, which is a bad thing to do.

You better tell what the original problem was, which you are trying to fix!

 

54 minutes ago, wintertime said:

If you need to ask a polymorphic object which type it is, you are most likely on the wrong way.

Yeah, this. It's a very strong hint that polymorphism is the wrong tool for your actual situation. If you tell us about the larger scale problem (of which needing to know object sizes is a sub-problem of) there's probably some much better architectures you could be using. 

That said, the most straightforward / simple solution to your actual question (besides a virtual Size method) is to put a public const int size member in the base class, and force every derived type to pass their size to the base's constructor. 

49 minutes ago, Hodgman said:

That said, the most straightforward / simple solution to your actual question (besides a virtual Size method) is to put a public const int size member in the base class, and force every derived type to pass their size to the base's constructor. 

Actually I do something like this now but I was trying to save the space. The only thing I need it for is deallocation.  This is for a specialized heap that uses 32 bit 8 byte aligned addresses, where all objects are derived from the same virtual class. I need the size to determine which free list the object goes in when it's deallocated.   It works now, it just seems like storing the size is a waste since all objects are virtual and theoretically the information could be stored with the vtable. In any case I don't really have to pass the size in since I can cheat and set the size in the new operator since I have to create a placement new anyway.

1 hour ago, Gnollrunner said:

I need the size to determine which free list the object goes in when it's deallocated

Is this the kind of allocator where you make pools for different sizes (e.g. a pool for <24 byte objects, a pool for <32 byte objects, etc)? If the pools themselves are a contiguous block of memory, then you can probably fairly quickly determine which pool an object was allocated from by the address.
e.g. 


//init a 1KB pool for 24B objects, and another for 32B objects
int poolSize = 1024;
int numPools = 2;
char* mem = malloc(poolSize*numPools);

char* begin24 = mem
int   capacity24 = poolSize / 24;
char* end24 = mem + capacity24 * 24;

char* begin32 = mem
int   capacity32 = poolSize / 32;
char* end32 = mem + capacity32 * 32;

//which pool is an object in?
void* object = ...
ptrdiff_t memOffset = object - mem;
int poolIndex = memOffset / poolSize; // 0 = 24B pool, 1 = 32B pool

 

5 hours ago, Hodgman said:

Is this the kind of allocator where you make pools for different sizes (e.g. a pool for <24 byte objects, a pool for <32 byte objects, etc)?

Sort of, but objects in the pools are interleaved randomly so I can't count on a specific range of memory locations for a given object. I'm using the Windows VirtualAlloc function to reserve an address range of 16 gig. Then I commit actual pages of memory as I need them. In any case I think I'll just stick with the size field for now and later I can try the virtual Size function thing and profile it to see what the speed difference is.

This topic is closed to new replies.

Advertisement