C ++: how to create an array of objects on the stack?

Consider the following Java code snippet.

int N = 10; Object obj[] = new Object[N]; for (int i = 0; i < N; i++) { int capacity = 1000 * i; obj[i] = new ArrayList(capacity); } 

Because in Java all objects live on the heap, the array does not contain the objects themselves, but references to the objects. Also, the array itself is also an object, so it lives on the heap.

What is the equivalent in C ++, but saving the array and objects onto the stack to avoid as many new ones as possible and delete them?

Edit: Changed the code to use a custom constructor.

+4
source share
6 answers

For an array of ArrayList objects:

 ArrayList obj[10]; 

Objects will be initialized by default, which is great for custom types, but may not be what you want for built-in types.

Consider also:

 std::vector<ArrayList> obj(10, ArrayList()); 

This initializes the objects, copying everything you pass as the second parameter. So they are all the same, but not necessarily default. And, as the bulb indicates, โ€œ10โ€ in a vector can be replaced with a non-constant expression, while โ€œ10โ€ in an array declaration cannot.

This does not actually push ArrayList objects onto the stack; it pushes all 10 in a single selection from the heap. Thus, there can very rarely be performance problems if you really cannot afford the highlight. However, std :: vector is on the stack and removes any heap objects that it uses when it is destroyed. So, in order to make sure that your resources are freed, the vector behaves as if they were all on the stack.

Note that mixing an Object container with ArrayList values, as in your Java code example, is fraught with danger in C ++. Basically you cannot do this even if ArrayList extends Object, because the array will only contain storage for 10 objects, and ArrayList probably requires more bytes to store than Object. As a result, any ArrayList that you are trying to copy into an array will receive a โ€œcutโ€: only the initial part of its representation is placed in the array.

If you need a container of type saying that it contains objects, but which actually contains ArrayLists, then you need a container of pointers. To get good resource handling, this probably means you need a smart pointer container.

+3
source

Just announcing

 Object array_of_objects[10]; 

in C ++ creates 10 built by default objects of type Object on the stack.

If you want to use a non-default constructor, this is not so simple in C ++. Perhaps there was a way to post a new one, but I could not tell you what was on my head.

EDIT: link to another question in StackOverflow How to use the new layout for an array is explained in the answer to this question here in StackOverflow.

+5
source

In C ++, it is impossible to have an array on the stack with a size defined at runtime. Here you use std :: vector to do this:

 int N = 10; std::vector<Object> obj(N); // non-default ctor: std::vector<Object> obj(N, Object(a1, a2)); // now they are all initialized and ready to be used 

If the size is known at compile time, you can simply use a simple array:

 int const N = 10; Object obj[N]; // non-default ctor: Object obj[N] = // { Object(a1, a2), Object(a2, a3), ... (up to N times) }; // now they are all initialized and ready to be used 

If you are allowed to use boost, it is better to use boost :: array, as it provides iterators like containers, and you can get its size using .size ():

 int const N = 10; boost::array<Object, N> obj; // non-default ctor: boost::array<Object, N> obj = // { { Object(a1, a2), Object(a2, a3), ... (up to N times) } }; // now they are all initialized and ready to be used 
+4
source

Selection can be performed โ€œstaticallyโ€ (size is known at compile time) or โ€œdynamicallyโ€ (size is determined at run time).

Static distribution is plain old

 int myarray[10]; 

To allocate on the stack, you will need the alloca distribution function, which essentially just increments the stack pointer. (or reduces ... anything). Cancellation is done automatically.

 int* myarray = (int*) alloca( n*sizeof(int) ); 

So, you can initialize the array on the stack, for example Niels .

std::vector can work on the stack if a stack allocator is provided (second, cumbersome argument to the vector template)

I guess Boost does just that.

+3
source

You can even allocate variable numbers of objects on the stack. You have to mix C and C ++ to do this, though.

 // allocate storage for N objects on the stack // you may have to call _alloca and include something to use this. object * data = (object *) alloca (N * sizeof (object)); // initialize via placement new. for (int i=0; i<N; i++) new (&data[i])(); 

The code is not verified, but in principle it works that way.

+2
source

If you use Qt, you can use QVarLengthArray

It takes size as the second parameter of the template, and it will statically allocate an array with that size and use it as the basis for the array instead of a heap like std :: vector or QVector. If you add more than the size specified in the template, heap distribution will be used instead.

Example:

 //the following ints will all be stored on the stack, //and a heap allocation is never performed to store the array QVarLengthArray<int, 10> objArray; for (int i = 0; i < 8; i++) { int capacity = 1000 * i; objArray.push_back(capacity); } //since it a class and not a raw array, we can get the array size std::cout << objArray.size(); //result is 8 //a heap allocation will be performed if we add an eleventh item, //since the template parameter of 10 says to only statically allocate 10 items objArray.push_back(0); //9 items objArray.push_back(0); //10 items objArray.push_back(0); //11 items - heap allocation is performed 

If you stay below the size of the template parameter, you will avoid the impact of heap allocation performance - you will effectively have a dynamically allocated array based on the stack. The only drawback is that it is wasteful of memory, if you do not use exactly as many elements as the template parameter sets: if you use too little, empty spaces are lost. if you use too much, then the whole selected area of โ€‹โ€‹the stack will be wasted.

Sometimes trading performance for memory is worth it, and sometimes it is not. I would recommend against using this class blindly - use it only if you know through profiling that the distribution of the std :: vector heap is one of your bottlenecks in your program.

0
source

All Articles