Statically allocating array of inherited objects - c++

The title of this question is pretty convoluted, so I'll try to frame it with an example. Let's say that I have an abstract base class, with a number of classes which inherit from it. In the example below I've only shown two inherited classes, but in reality there could be more.
class Base {
public:
Base();
virtual ~Base() = 0;
/// Other methods/members
};
class SmallChild: public Base {
public:
SmallChild();
~SmallChild();
/// Other methods/members such that sizeof(SmallChild) < sizeof(LargeChild)
};
class LargeChild : public Base {
public:
LargeChild();
~LargeChild();
/// Other methods/members such that sizeof(LargeChild) > sizeof(SmallChild)
};
I need to implement a container which stores up to N inherited objects. These objects need to be created/destroyed at runtime and placed in the container, but due to constraints in the project (specifically that it's on embedded hardware), dynamic memory allocation isn't an option. The container needs to have all of its space statically allocated. Also, C++11 is not supported by the compiler.
There was only one way I could think to implement this. To reference the N objects, I'd first need to create an array of pointers to the base class, and then to actually store the objects, I'd need to create a buffer large enough to store N copies of the largest inherited object, which in this case is LargeChild
Base * children[N];
uint8_t childBuffer[N * sizeof(LargeChild)];
I could then distribute the pointers in children across childBuffer, each separated by sizeof(LargeChild). As objects need to be created, C++'s "placement new" could be used to place them at the specified locations in the array. I'd need to keep track of the type of each object in childBuffer in order to dereference the pointers in children, but this shouldn't be too bad.
I have a few questions regarding this entire setup/implementation:
Is this a good approach to solving the problem as I've described it? I've never implemented ANYTHING like this before, so I have no idea if I'm way out to lunch here and there's a much easier way to accomplish this.
How much of this can be done at compile-time? If I have M types of inherited classes (SmallChild, LargeChild, etc.) but I don't know their size in relation to each other, how can I determine the size of childBuffer? This size depends on the size of the largest class, but is there a way to determine this size at compile-time? I can imagine some preprocessor macros iterating through the classes, evaluating sizeof and finding the maximum, but I have very little experience with this level of preprocessor work and have no idea what this would look like. I can also imagine this being possible using templates, but again, I don't have any experience with compile-time template sorcery so I'm only basing this on my intuition. Any direction on how to implement this would be appreciated.

Do you need to be able to dealocate the objects? If not, it may be easier to override operator new. I refer to this:
void* operator new (std::size_t size) throw (std::bad_alloc);
All your overrides would allocate memory from a sinle large buffer. How much memory to allocate is specified by the size parammeter.
This way you should be able to just say
children[i] = new SmallChild();
Edit: if you do need to deallocate, you need more complex data structures. You may end up re-implementing the heap anyway.

If the set of objects is fully static (set at build time and doesn't change at runtime), the usual approach is to use a set of arrays of each derived class and build up the 'global' array with pointers into the other arrays:
static SmallChild small_children[] = {
{ ...initializer for first small child... },
{ ...initializer for second small child... },
...
};
static LargeChild large_children[] = {
{ ...initializer for first large child... },
...
};
Base *children[N] = { &small_children[0], &small_children[1], &large_children[0], ....
This can be tricky to maintain if there are children being added/removed from the build frequently, or if the order in the children array is important. It may be desirable to generate the above source file with a script or build program that reads a description of the children needed.

Your approach is interesting, given your constraints (i.e. no use of dynamic allocation).
In fact you are managing on your own way a kind of array of union anyChild { smallChild o1; largeChild o2; ... }; The sizeof(anyChild) would give you the largest block size you are looking for.
By the way, there could be a risk of dangling pointers in you approach, as long as all objects have not been created with the the placement new, or if some of them are deleted through explicit call of their destructor.

if you put your derived types into a union:
union Child{
SmallChild asSmallChild;
LargeChild asLargeChild;
}
Then the union will automatically be of the sizeof the largest type. Of course, now you have a new problem. What type is represented in the union? You could give yourself a hint in the base Class, or you could instead make Child a struct which contains a hint and then the union inlined within. For examples look at components made by Espressif for ESP32 on the githubs, lots of good union uses there.
Anyways, when you go to allocate, if you allocate an array of the union'ed type it will make an array of largest children... because that's what unions do.

Related

Improve storage capacity / performance of std::vector

I am building a modelling software I had a few questions about how to get the best performance ?
1) Should I use std::vector<class> or std::vector<class*> ?
My class is quite complicated / big , and I think using the second option is better , as since std::vector tries to allocate memory contiguously and there might not be a contiguous block of memory to store a million class, but when I just store pointers, the class does not have to be stored contiguously only the pointers have to stored and the computer might have space to do this. Is this reasoning correct?
2) As I said I will have millions of class, (for proper simulation I will need > billion of the class ) is inheritance a smart thing to use here ?
For my simulation , there are multiple different types which inherits from the same base class,
class A - class B
- class C
- class D
Should I avoid inheritance as I keep hearing that there is a performance penalty for using inheritance ?
3) Also how do I store all these different class in a std::vector ?
Can a std::vector<base_class * > or std::vector<base_class> store class B , class C , class D which all inherit from the base class ?
4) In the previous version of the program , I used multi threading by making the different process handle different sections of the std::vector , is there a better way to do the threading ?
5) Should I use smart pointers ? Since I have so many objects , will they degrade performance ?
I am in the planning stage and any help is greatly appreciated.
I deal with problems like this every day in a professional setting (I'm a C++ programmer by trade, dealing with big-data sets). As such what I'm about to say here is as much personal-advice as it is an answer. I won't go all out on the simple parts:
1 - Yes store pointers, it will be much faster than reallocation and move times than the full class-object.
2 - Yes, use inheritance if the objects have information in relation, I imagine in this case they most likely do as your considering it. If they don't, why would you store them together?
3 - Store them all using smart pointers to the base-class (the parent object, thus you can add a single virtual "get_type" function to return and enumeration, and convert to a child when you need to. This will save the overhead of providing multiple virtual-methods if you don't need child-data often.
4 - Arguable, but threading separate parts of a larger array is the simpler approach (and when your dealing with huge complexity of data, simpler is better.
Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it? ~ Brian Kernighan
5 - There will be some small penalty for using smart pointers ( As explained in this question, however in my opinion that penalty (especially with the unique_ptr) is so small compared to the ease-of-use and loss of complexity, it's definitely worth it
And putting it all together:
class Abstract_Parent;
std::vector<std::unique_ptr<Abstract_Parent>> Data;
enum ChildType {Child_1 = 0, Child_2 = 1};
class Abstract_Parent
{
public:
virtual ChildType GetType() = 0;
}
class Child_One
{
public:
virtual ChildType GetType() { return Child_1; }
}
class Child_Two
{
public:
virtual ChildType GetType() { return Child_2; }
}
void Some_Function()
{
//this is how to insert a child-object
std::unique_ptr<Abstract_Parent> Push_me_Back(new Child_One());
Data.Push_Back(std::move(Push_me_Back));
if(Data[0]->GetType() == Child_1)
{
Child_1 *Temp_Ptr = dynamic_cast<Child_One*> Data[0];
Temp_Ptr->Do_Something_Specific();
}
}
1.) That depends on your use case. You will use a pointer if you want to access object through a base class pointer. On the other side you lose the advantage of continuous memory and cache locality of code and data.
2.) If you need 1 billion instance then every additional data per object will increase you memory footprint. For example an additional pointer to your virtual function table (vptr) of 8 bytes will increase your memory requirements by 8 GBytes. Storing every type in a different vector without a virtual base class does not have this overhead.
2b) Yes you should avoid inheritance with virtual function if you aim for performance. The instruction cache will be trashed if virtual function are called with different implementations. At least you can sort your big vector by type to minimize this problem.
3.) You must use the pointer option to prevent slicing if you go for a base class with virtual functions.
4.) More information is needed and should be answered in separate question.
5.) Every indirection will degrade performance.
1) Should I use std::vector<class> or std::vector<class*> ?
False dicotomy. There are a couple of other options:
boost::ptr_vector<class>
std::vector<std::unique_ptr<class>>
Probably even more.
Personally I like boost::ptr_vector<class> as it stores an owned pointer (thus memory allocation is done automatically). But when accessing members they are returned as reference to the object (not pointers). Thus using them with standard algorithms is vastly simplified over other techniques.
My class is quite complicated / big , and I think using the second option is better , as since std::vector tries to allocate memory contiguously and there might not be a contiguous block of memory to store a million class,
The real question here is if you can pre-calculate the maximum size of your vector and reserve() the required amount of space. If you can do this (and thus avoid any cost of copying) std::vector<class> would be the best solution.
This is because having the objects in contiguous storage is usually a significant advantage in terms of speed (especially when scanning a vector). The ability to do this should not be underestimated when you have huge datasets (especially in the billion range).
but when I just store pointers, the class does not have to be stored contiguously only the pointers have to stored and the computer might have space to do this. Is this reasoning correct?
By using pointers, you are also significantly increasing the amount of memory required by the application as you need to store the object and the pointer to the object. Over billions of objects this can be a significant cost.
2) As I said I will have millions of class, (for proper simulation I will need > billion of the class ) is inheritance a smart thing to use here ?
Impossible to say without much more information.
3) Also how do I store all these different class in a std::vector ? Can a std::vector or std::vector store class B , class C , class D which all inherit from the base class ?
But if you do use inheritance you will need not be able to use std::vector<class> directly. You will need to store a pointer to the base class. But that does not preclude the other three techniques.
4) In the previous version of the program , I used multi threading by making the different process handle different sections of the std::vector , is there a better way to do the threading ?
This seems a reasonable approach (assuming that the ranges don't overlap and are contiguous). Don't create more threads than you have available cores.
Should I use smart pointers ? Since I have so many objects , will they degrade performance ?
Use of unique_ptr over a normal pointer has zero overhead (assuming you don't use a custom deleter). The actual generated code will be basically equivalent.

Vector of base and inherited objects

How would one go about creating a vector that includes both the base class as well as any derived classes?
For example, in a chess engine, I currently have a Move class which stores a particular move and a few functions to help it. In order to save memory, as millions of these objects are going to be created, I also have a derived class CaptureMove that extends the Move class storing a bit more information about what and where the piece was captured.
From what I can gather, pointers to Move objects should work, but I'm not quite sure on how to go about it.
The question is quite broad. Here some ideas:
Vectors of base pointers:
This works extremely well if your class is polymorphic (i.e. the relevant functions of the base class are virtual).
vector<Move*> mp;
mp.push_back (new Move); // attention, you have to delete it ofr memory will leak
mp.push_back (new CaptureMove);
It the simplest way to proceed. However you have to make sure that when you add an object, it's allocated properly (e.g. created with new), and that once you no longer need it, you delete it. This can be very cumbersome, especially if vector was copied and some of its pointers are still in use.
This approach can be practical for example if you create and delete the objects in a centralised manner, so that the vector only uses pointers which are properly managed somewhere else.
Vector of shared base pointers:
vector<shared_ptr<Move>> m;
m.push_back(make_shared<Move>());
m.push_back(make_shared<CaptureMove>());
m.push_back(make_shared<Move>());
Here an online demo.
It extends the pointer solution, using smart pointers to take care of the release of unused objects.
Honestly, it's a little overhead but it's really worth it, in order to have reliable code. This is the approach I would take personnally if I'd have to do it.
Vector of compound object
You could also prefer to store the object instead of a pointer to the object. While the idea seems simple, it's more difficult to do, because different derivates could have different size. And it has serious drawbacks, because you'd need to know all possible base and derived types you may store in the vector, which makes this approach less flexible.
You could certainly manage this with a complex union, but the easiers way would be to use boost::variant.
vector<boost::variant<Move, CaptureMove>> m;
This approach is only worth considering if the number of derived classes is very limited, but you have huge numbers of small objects (so that memory allocation would become a real overhead) of almost the same size.

Alternatives for polymorphic data storage

I'm storing a large amount of computed data and I'm currently using a polymorphic type to reduce the amount of storage required. Everything is extremely fast except for deleting the objects when I'm finished and I think there must be a better alternative. The code computes the state at each step and depending on the conditions present it needs to store certain values. The worst case is storing the full object state and the best state is storing almost nothing. The (very simplified) setup is as follows:
class BaseClass
{
public:
virtual ~BaseClass() { }
double time;
unsigned int section;
};
class VirtualSmall : public BaseClass
{
public:
double values[2];
int othervalue;
};
class VirtualBig : public BaseClass
{
public:
double values[16];
int othervalues[5];
};
...
std::vector<BaseClass*> results(10000);
The appropriate object type is generated during computation and a pointer to it is stored in the vector. The overhead from vtable+pointer is overall much smaller than than the size difference between the largest and smallest object (which is least 200 bytes according to sizeof). Since often the smallest object can be used instead of the largest and there are potentially many tens of millions of them stored it can save a few gigabytes of memory usage. The results can then be searched extremely fast as the base class contains the information necessary to find the correct item which can then be dynamic_cast back to it's real type. It works very well for the most part.
The only issue is with delete. It takes a few seconds to free all of the memory when there is many tens of millions of objects. The delete code iterates through each object and delete results[i] which calls the virtual destructor. While it's not impossible to work around I think there must be a more elegant solution.
It could definitely be done by allocating largish contiguous blocks of memory (with malloc or similar), which are kept track of and then something generates a correct pointers to the next batch of free memory inside of the block. That pointer is then stored in the vector. To free the memory the smaller number of large blocks need to have free() called on them. There is no more vtable (and it can be replaced by a smaller type field to ensure the correct cast) which saves space as well. It is very much a C style solution though and not particularly pretty.
Is there a C++ style solution to this type of problem I'm overlooking?
You can overload the "new" operator (i.e. void* VirtualSmall::operator new(size_t) ) for you classes, and implement them to obtain memory from custom allocators. I would use one block allocator for each derived class, so that each block size is a multiple of the class' it's supposed to store.
When it's time to cleanup, tell each allocators to release all blocks. No destructors will be called, so make sure you don't need them.

Is it unefficient to use a std::vector when it only contains two elements?

I am building a C++ class A that needs to contain a bunch of pointers to other objects B.
In order to make the class as general as possible, I am using a std::vector<B*> inside this class. This way any number of different B can be held in A (there are no restrictions on how many there can be).
Now this might be a bit of overkill because most of the time, I will be using objects of type A that only hold either 2 or 4 B*'s in the vector.
Since there is going to be a lot of iterative calculations going on, involving objects of class A, I was wondering if there is a lot of overhead involved in using a vector of B's when there are only two B's needed.
Should I overload the class to use another container when there are less than 3 B present?
to make things clearer: A are multipoles and B are magnetic coils, that constitute the multipoles
Premature optimization. Get it working first. If you profile your application and see that you need more efficiency (in memory or performance), then you can change it. Otherwise, it's a potential waste of time.
I would use a vector for now, but typedef a name for it instead of spelling std::vector out directly where it's used:
typedef std::vector vec_type;
class A {
vec_type<B*> whatever;
};
Then, when/if it becomes a problem, you can change that typedef name to refer to a vector-like class that's optimized for a small number of contained objects (e.g., does something like the small-string optimization that's common with many implementations of std::string).
Another possibility (though I don't like it quite as well) is to continue to use the name "vector" directly, but use a using declaration to specify what vector to use:
class A {
using std::vector;
vector<B*> whatever;
};
In this case, when/if necessary, you put your replacement vector into a namespace, and change the using declaration to point to that instead:
class A {
using my_optimized_version::vector;
// the rest of the code remains unchanged:
vector<B*> whatever;
};
As far as how to implement the optimized class, the typical way is something like this:
template <class T>
class pseudo_vector {
T small_data[5];
T *data;
size_t size;
size_t allocated;
public:
// ...
};
Then, if you have 5 or fewer items to store, you put them in small_data. When/if your vector contains more items than that fixed limit, you allocate space on the heap, and use data to point to it.
Depending a bit on what you're trying to optimize, you may want to use an abstract base class, with two descendants, one for small vectors and the other for large vectors, with a pimpl-like class to wrap them and make either one act like something you can use directly.
Yet another possibility that can be useful for some situations is to continue to use std::vector, but provide a custom Allocator object for it to use when obtaining storage space. Googling for "small object allocator" should turn up a number of candidates that have already been written. Depending on the situation, you may want to use one of those directly, or you may want to use them as inspiration to write your own.
If you need an array of B* that will never change its size, you won't need the dynamic shrinking and growing abilities of the std::vector.
So, probably not for reasons of efficiency, but for reasons of intuition, you could consider using a fixed length array:
struct A {
enum { ndims = 2 };
B* b[ndims];
};
or std::array (if available):
struct A {
std::array<B*, 2> b;
};
see also this answer on that topic.
Vectors are pretty lean as far as overhead goes. I'm sure someone here can give more detailed information about what that really means. But if you've got performance issues, they're not going to come from vector.
In addition I'd definitely avoid the tactic of using different containers depending on how many items there are. That's just begging for a disaster and won't really give you anything in return.

why to use non-pointer for c++ fields?

In these days I'm starting to get my feet wet with c++ and, due to my Java-ish background, I obviously have some problems in understanding some c++ features.
Since java offers only references and primitives one of the most mysterious c++ feature for me is non-pointer (and non-primitive) fields.
Here is an example of what I mean.
If I should write a c++ implementation in c++ of a list of objects of type X I would write something like:
class XList{
private:
struct node {
X* data;
node* next;
};
node* first;
public:
*/
a lot of methods
*/
}
This code is probably awful, I know about templates, STL and whatnot but the problem for me here is just the field "data". If a declare "data" as a X pointer I presume that I can use it in a way very similar to Java references.
What could be instead the reason to declare data as a X (X data;). What is the difference? I know the difference between allocating on the stack and on the heap but is there any connection here?
Please help me get a bit more of a grip on this topic.
Thank you.
--- UPDATE: ----
Most of the answers seem to focus on the difference between using the plain type on a pointer in general.
Probably I wrote the question in the wrong way, but I already know the difference between allocating on the stack or on the heap (the basics at least).
What I can't understand is that in my (probably wrong) opinion the usage of a plain type in a member variables (not field, thank you for your correction) should be just some kind of corner case. Especially when templates are involved a copy of the data makes no sense to me.
Instead every time I see an implementation of some data structure the plain type is used.
E.g.: If you search "bst c++ template" on google you will find a lot of implementation like this one:
template<class T>
class BinarySearchTree
{
private:
struct tree_node
{
tree_node* left;
tree_node* right;
T data;
};
tree_node* root;
public:
/*
methods, methods and methods
*/
};
Do you really want to make a copy of every data of type T inserted on this tree without knowing its size? Since I'm new to the language I suppose that I misunderstood something.
The advantage of using an X instead of an X * is that with the pointer, you have to allocate the space for the X as well, which uses more space (4 bytes or 8 bytes for the pointer, plus the overhead of the allocation for the X via new), whereas with the plain type, you avoid that overhead. So, it is simpler just to use the plain X.
You'd use the pointer when you definitively do not want to make a copy of the X value, but you could end up with dangling pointers if you are not careful. You'd also use the pointer if there are circumstances where you might not have an object to point to.
Summary
Use the direct object to simplify memory management.
Use the pointer when you cannot afford copying or need to represent the absence of a value.
The difference is that a pointer points to an as yet allocated or determined hunk of memory. But when you leave off the *, you're saying "allocated space for this entire class (not just a pointer to a class) along with this class."
The former, using a pointer, puts all the memory allocation and maintenance in your hands. The latter just gives you the object as a member of your class.
The former doesn't use much space (what, four to eight bytes, depending on architecture?) The latter can use a little up to a LOT depending on what the class X has as its member.
I use non-pointer data members when: 1) I'm sure this data shouldn't and won't be shared among objects 2) I can rely on automatic deallocation when the oject is finally destroyed. A good example is a wrapper (of something to be wrapped):
class Wrapper
{
private:
Wrapped _wrapped;
public:
Wrapper(args) : _wrapped(args) { }
}
The primary difference is that if you declare an X* you're responsible for memory management (new and delete) on the heap, while with an X the memory is handled on the stack, so it's allocated/freed with the scope.
There are other subtle things as well, like worrying about assignment to self, etc.