Variable-length objects: always a good idea?

My application uses a large number of Panda objects. Each Panda has a list of Bamboo objects. This list does not change after Panda initialization ( Bamboo objects are added or deleted). Currently, my class is implemented as follows:

 class Panda { int a; int b; int _bambooCount; Bamboo* _bamboo; Panda (int count, Bamboo* bamboo) { _bambooCount = count; _bamboo = new Bamboo[count]; // ... copy bamboo into the array ... } } 

To ease the overhead of allocating an array of Bamboo objects, I could implement this class as follows: basically, instead of creating objects through a regular constructor, the construction method allocates one memory block for storage like Panda and its Bamboo array:

 class Panda { int a; int b; Panda () { // ... other initializations here ... } static Panda *createPanda (int count, Bamboo* bamboo) { byte* p = new byte[sizeof(Panda) + sizeof(Bamboo) * count]; new (p) Panda (); Bamboo* bamboo = (Bamboo*) p + sizeof(Panda); // ... copy bamboo objects into the memory // behind the object... return (Panda*)p; } } 

Can you anticipate any problems with the second design besides increasing the maintenance effort? Is this an acceptable design pattern or just a premature optimization that could bite me again?

+6
c ++ design-patterns data-structures class-design
source share
7 answers

C ++ gives you another option. You should use std :: vector.

 class Panda { int a; int b; std::vector<Bamboo> bamboo; // if you do not want to store by value: //std::vector< shared_ptr<Bamboo> > bamboo; Panda (int count, Bamboo* bamb) : bamboo( bamb, bamb+count ) {} } 

If you want to store Panda and Bamboos in continuous memory, you can use the solution from this article . The main idea is to overload operator new and operator delete .

+9
source share

How do we convince people that simplicity and clarity are short in programming: what mathematicians call "elegance" is not a luxury of luxury, but a decisive question that decides between success and failure?

- Edser W. Dijkstra

+7
source share

You will be bitten if someone takes Panda by value, for example.

 //compiler allocates 16-bytes on the stack for this local variable Panda panda = *createPanda(15, bamboo); 

This may be acceptable (but most likely it is premature and horrible optimization) if you ever refer to things by pointer and never by value, and if you are wary of the copy constructor and assignment operator.

+4
source share

Based on my experience, premature optimization is most always “premature”. That is, you must profile your code and determine whether you need optimization or if you simply create more work for yourself in the long run.

In addition, it seems to me that the questions about whether the optimization is worth it or not depend heavily on the size of the Bamboo class and the average number of Bamboo objects per Panda.

+3
source share

It was found in C.
But in C ++ there is no real need.

The real question is, why do you want to do this?

This is a premature optimization, just use std :: vector <> inside and all your problems will go away.

Since you are using an internal RAW pointer that belongs to the class, you need to override the default versions:

  • Default constructor
  • Destructor
  • Copy constructor
  • Assignment operator
+3
source share

If you are desperate, you can do something like this:

 template<std::size_t N> class Panda_with_bamboo : public Panda_without_bamboo { int a; int b; Bamboo bamboo[N]; } 

But I believe that you are not in despair, but prematurely optimize.

+2
source share

You are using the "new" view of the new operator. This is a completely correct relative Panda, but why don't you use the Bamboo initializer?

+1
source share

All Articles