Creating array of objects on the stack and heap
Asked Answered
B

6

28

Consider the following code:

class myarray
{
    int i;

    public:
            myarray(int a) : i(a){ }

}

How can you create an array of objects of myarray on the stack and how can you create an array of objects on the heap?

Brian answered 21/10, 2009 at 2:13 Comment(2)
Is this a homework question? It sounds like one.Nat
Nope...This is not a homework question...Found this on the internet while preparing for my job interview....:)Brian
M
62

You can create an array of objects on the stack via:

myarray stackArray[100]; // 100 objects

And on the heap (or "freestore"):

myarray* heapArray = new myarray[100];
delete [] heapArray; // when you're done

But it's best not manage memory yourself. Instead, use a std::vector:

#include <vector>
std::vector<myarray> bestArray(100);

A vector is a dynamic array, which (by default) allocates elements from the heap.††


Because your class has no default constructor, to create it on the stack you need to let the compiler know what to pass into the constructor:

myarray stackArray[3] = { 1, 2, 3 };

Or with a vector:

// C++11:
std::vector<myarray> bestArray{ 1, 2, 3 };

// C++03:
std::vector<myarray> bestArray;
bestArray.push_back(myarray(1));
bestArray.push_back(myarray(2));
bestArray.push_back(myarray(3));

Of course, you could always give it a default constructor:

class myarray
{
    int i;    
public:
    myarray(int a = 0) :
    i(a)
    {}
};

† For the pedants: C++ doesn't really have a "stack" or "heap"/"freestore". What we have is "automatic storage" and "dynamic storage" duration. In practice, this aligns itself with stack allocation and heap allocation.

†† If you want "dynamic" allocation from the stack, you'd need to define a max size (stack storage is known ahead of time), and then give vector a new allocator so it uses the stack instead.

Matchmark answered 21/10, 2009 at 2:18 Comment(7)
you can use _alloca() to dynamically allocate variable amounts of memory on the stack...Virgate
@GMan - It's a nonstandard but widely provided C function.Messaline
It works the same way in C++ that it does in C; if there's a more standard way to tell the compiler to allocate N bytes on the stack where N is determined at runtime, I don't know what it is.Virgate
just a very little detail maybe, I'm not sure if vector specifies that elements will be on the heap. for example classic string implementation keeps the characters inside the object itself up to 8 or 16 characters in general. then when it needs to elongate it switches to heap. So if the string object itself is on the stack the data is on the stack too, for all strings smaller than 16. One could imagine vector could act the same in implementations, no ?Gudrun
Shouldn't the array of objects be a double pointer?? Since every object is a pointer when saved on the heapInteraction
@Gudrun why did the creators of C++ allocate vector memory on the heap? As we know vectors are also contiguous in memory and need re-allocation in case the user of the vector exceeds the vector's initial capacity. This can be done on the stack as well. Or am I missing something?Recor
@Recor the only thing the standard says about vector is supports random access iterators. In addition, it supports (amortized) constant time insert and erase operations at the end; insert and erase in the middle take linear time. Storage management is handled automatically, though hints can be given to improve efficiency. The elements of a vector are stored contiguously in my opinion it means where the data goes is up to the allocator. Could be the stack but O(move) would be a O(copy) (I don't know if complexity is a constraint in allocators)Gudrun
S
8

Since C++11 std::array<T,size> is available for arrays allocated on the stack. It wraps T[size] providing the interface of std::vector, but the most of the methods are constexpr. The downside here is that you never know when you overflow the stack.

std::array<myarray, 3> stack_array; // Size must be declared explicitly.VLAs

For arrays allocated with heap memory use std::vector<T>. Unless you specify a custom allocator the standard implementation will use heap memory to allocate the array members.

std::vector<myarray> heap_array (3); // Size is optional.

Note that in both cases a default constructor is required to initialize the array, so you must define

myarray::myarray() { ... }

There are also options to use C's VLAs or C++'s new, but you should refrain from using them as much as possible, because their usage makes the code prone to segmentation faults and memory leaks.

Spoilfive answered 7/1, 2016 at 7:36 Comment(1)
std::array is good because - like any other well-programmed wrapper around a T[n] - it knows its own size (via template magic), can be passed around in a more pleasing way, can be returned from functions, etc. I did like "you never know when you overflow the stack" - well, except when it causes totally random corruption of non-stack memory and makes itself very obvious :-) but of course, it's best to avoid allocating huge arrays on the stack.Roobbie
L
2

If you create an array of objects of class myarray ( either on stack or on heap) you would have to define a default constructor.

There is no way to pass arguments to the constructor when creating an array of objects.

Luckless answered 21/10, 2009 at 2:34 Comment(0)
C
1

I know how to create object with out of the default constructor, but only on stack:

Suppose you want to create 10 objects for MyArray class with a = 1..10:

MyArray objArray[] = { MyArray[1], MyArray[2]......MyArray[10]}

No need to call the destructor, because they are created in the stack.

Cubiculum answered 3/11, 2010 at 2:35 Comment(2)
Syntax? Use round brackets, the following uses temporarie: MyArray objArray[] = { MyArray(0), MyArray(88), etc., }Disport
As mentioned, this would not compile.Roobbie
B
0

To use stack memory allocated with a max size, and view it through a standard stl container with a run time chosen size, you can use std::span.

#include <span>
using namespace std;

struct Toto{ int i; char name[20];};
Toto mem[100];
int n=3;
std::span<Toto> s(&mem[0], n);

my use case involves a function that gets called a million times and makes use of a few arrays (currently std::vectors). I wonder if it would be faster to replace std::vector this way. Havent't tried yet... Another possibility would be to allocate std::vector's once instead of a million times.

Boar answered 16/7, 2022 at 19:13 Comment(0)
B
-1
#include <stdio.h>
class A
{
public:
  A(int a){ 
       printf("\nConstructor Called : %d\n",a); 
       aM = a;
      }  
  ~A(){ 
    printf("\ndestructor Called : %d\n",aM);
}
private:
  int aM;
};

int main()
{                                                                                                   
  A **a = new A*[10];
  for (int i = 0;i<10;i++)
    a[i] = new A(i+1);
    for (int i = 0;i<10;i++)
      delete a[i];// = new A(i+1);                                                                                    

  delete []a;
}
Brandonbrandt answered 7/9, 2011 at 14:11 Comment(1)
I also fail to see where there is any array of A, unless objects count as arrays of size 1.Placable

© 2022 - 2024 — McMap. All rights reserved.