MyClass *myVar;
myVar = new MyClass[num];

Actually in this form you cannot invoke constructor which takes parameter(s). It is not allowed by the language specification.

However, if you use std::vector, which I recommend you to use, then you can create a vector calling non-default constructor as:

#include <vector> //header file where std::vector is defined

std::vector<MyClass>  arr(num, MyClass(10,20));

It creates a vector of num elements, each element is created by calling copy-constructor of the class, passing MyClass(10,20) as argument to it.

The vector is also good because now you dont need to manage memory yourself. Neither manual allocation, nor manual deallocation. Plus, you can know the number of elements by calling arr.size() anytime. You always know how many elements the vector contains. You can also add elements anytime, just by calling .push_back() member function as:

arr.push_back(MyClass(20,30)); 

And now you can access elements, just like you access array, i.e by using index:

f(arr[i]); // 0 <= i < arr.size();

Additionally, you can use iterators which facilitate idiomatic programming, enabling you to use various algorithmic functions from <algorithm> header as:

#include <algorithm> //header file where std::for_each is defined

std::for_each(arr.begin(), arr.end(), f);

where f is function which takes one argument of type MyClass& (or MyClass const &) depending on what you want to do in f.

In C++11, you can use lambda as:

std::for_each(arr.begin(), arr.end(), 
                                      {
                                           //working with m 
                                      });
Answer from Sarfaraz Nawaz on Stack Overflow
Top answer
1 of 6
32
MyClass *myVar;
myVar = new MyClass[num];

Actually in this form you cannot invoke constructor which takes parameter(s). It is not allowed by the language specification.

However, if you use std::vector, which I recommend you to use, then you can create a vector calling non-default constructor as:

#include <vector> //header file where std::vector is defined

std::vector<MyClass>  arr(num, MyClass(10,20));

It creates a vector of num elements, each element is created by calling copy-constructor of the class, passing MyClass(10,20) as argument to it.

The vector is also good because now you dont need to manage memory yourself. Neither manual allocation, nor manual deallocation. Plus, you can know the number of elements by calling arr.size() anytime. You always know how many elements the vector contains. You can also add elements anytime, just by calling .push_back() member function as:

arr.push_back(MyClass(20,30)); 

And now you can access elements, just like you access array, i.e by using index:

f(arr[i]); // 0 <= i < arr.size();

Additionally, you can use iterators which facilitate idiomatic programming, enabling you to use various algorithmic functions from <algorithm> header as:

#include <algorithm> //header file where std::for_each is defined

std::for_each(arr.begin(), arr.end(), f);

where f is function which takes one argument of type MyClass& (or MyClass const &) depending on what you want to do in f.

In C++11, you can use lambda as:

std::for_each(arr.begin(), arr.end(), 
                                      {
                                           //working with m 
                                      });
2 of 6
9

In C++0x, this grammar works, which can call the non-default constructor in new expression:

MyClass *myVar;
myVar = new MyClass[2]{{10, 20},{20, 30}};

But I doubt if it works when the number of elements in available only at run time.

The vector approach would be better, as shown in Nawaz's answer.

🌐
Florida State University
cs.fsu.edu › ~myers › cop3330 › notes › dma.html
Dynamic Allocation in Classes
For a dynamically created array, the pointer attaches to the starting position of the array, so can act as the array name: ... Just like basic types, objects can be allocated dynamically, as well. But remember, when an object is created, the constructor runs.
Discussions

c++ - Dynamic arrays inside a class - Stack Overflow
In matrix operations we are going ... the members of Matrix as an array. Also, we are going to need to change the size of the data stored in the matrix, therefore it should be dynamically allocated. ... Create the following three constructors: Matrix() • Default constructor, ... More on stackoverflow.com
🌐 stackoverflow.com
copy constructor - c++ dynamic arrays in class - Stack Overflow
I am trying to create an example with dynamic arrays in class in order to user destructor and copy constructor. The idea of the program is the following. I have class Labtest with two private fie... More on stackoverflow.com
🌐 stackoverflow.com
April 2, 2018
c++ - How do I initialize a dynamically allocated array within a class constructor - Stack Overflow
I'd suggest making the following change. A::A(){ maxNumberOfItems=10; b = new B[maxNumberOfItems]; // b is an array of B objects. // with default constructed values // This way avoids the need for using a for loop and reassigning values } ~A(){ if (b != NULL) { delete b; } } class B{ private: //.... public: B(): name(""), price(0) {} // Although the default constructor ... More on stackoverflow.com
🌐 stackoverflow.com
C++ copy constructor for class with dynamically allocated array - Stack Overflow
Just starting on C++ (a few days now), I come with C background. I have a class that holds, mainly, an a pointer to an int array with the following code: class Array { private: int * _arr; ... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Cplusplus
cplusplus.com › forum › general › 107004
Classes, dynamic arrays, constructors, and overloading
You managed to get the destructor, the default constructor, operator[] and size correct. Everything else is wrong and would result in very odd behavior if you did actually exercise the class. Don't say you've tested stuff you haven't tested. It's irksome. ... Yea, never tested that function. That's fixed, however in my most recent build. Topic archived. No new replies allowed. Home page | Privacy policy © cplusplus...
🌐
Simon Fraser University
www2.cs.sfu.ca › CourseCentral › 125 › tjd › int_vec_class_tutorial1_cpp.html
A Dynamic Array Using a Class (Part 1) — 125 Summer 2020 1 documentation
The destructor is where // dynamic memory, or any other resource used by the object, can be // de-allocated. Since the destructor is called automatically, the programmer // never needs to worry about calling. Indeed, you cannot explicitly call a // destructor! // // Lets add a constructor to our int_vec class to create a new empt int_vec:: // // class int_vec { // private: // int capacity; // length of underlying array // int* arr; // pointer to the underlying array // int size; // # of elements in this int_vec from user's perspective // public: // // // Default constructor (takes no parameter
🌐
GeeksforGeeks
geeksforgeeks.org › c++ › dynamic-constructor-in-c-with-examples
Dynamic Constructor in C++ with Examples - GeeksforGeeks
July 11, 2025 - The first object is ptr[0], second is ptr[1] and so on . For each object creation default constructor is called and for each object memory is allocated to pointer type variable by new operator.
Find elsewhere
Top answer
1 of 3
4

You should allocate memory before using dynamic array.I have allocated memory for b

class A //in a.h

{

private:

    B * b;

    int maxNumberOfItems;

    //...

public:

A();

~A();

void addB(const B & something);

};

//in a.cpp

A::A()

{
    maxNumberOfItems=10;
    b = new B[maxNumberOfItems];

    for(int i=0;i<maxNumberOfItems;i++)
    {
    b[i]="";//has to be an empty string, I am getting a segmentation fault
    }

}

A::~A(){/*...*/}

//...

//in b.h

class B
{

private:

    string name;

    int price;

public:

    void setName(string);

    string getName();

    void setPrice();

    int getPrice(int);

    B & operator=(string &);

};

//in b.cpp

B & B::operator=(string & a){name = a;price = 0; return *this;}
2 of 3
3

It looks like class A is supposed to be a dynamic array class.

When you create a new instance of A you must also allocate memory for your array b. Which is just a pointer to some point in memory. From the code you posted, it doesn't get initialized and can point to any random memory place -- which is not good (i.e. the likely cause of your segfault).

I'd suggest making the following change.

A::A(){
  maxNumberOfItems=10;
  b = new B[maxNumberOfItems]; // b is an array of B objects.
                               // with default constructed values
  // This way avoids the need for using a for loop and reassigning values
}

~A(){
  if (b != NULL) { delete b; }
}

class B{
  private:
    //....
  public:
     B(): name(""), price(0) {}
    // Although the default constructor without defining one should behave the same.
    // This just makes it explicit. what name and price default to.
}
Top answer
1 of 5
8

This:

Array::Array( const Array & obj )
{
    _arr = new int[_size];

    for(int i=0;i<_size;i++)
        *_arr[i] = *obj._arr[i];
}

could be this:

Array::Array( const Array & obj )
    : _arr(obj._size ? new int[obj._size] : nullptr)
    , _size(obj._size)
{
    if (_arr)
        std::copy(obj._arr, obj._arr+_size, _arr);
}

Specifically, note the use of the initializer list. Other things worth mentioning:

  1. Don't use identifiers with leading underscores. Besides making the code a royal pain to read, you can quickly find yourself using identifiers that are reserved by the implementation. That isn't the case here, but I'm willing to bet that wasn't by intent.

  2. You also need an assignment operator to fulfill the Rule of Three. Thankfully, a decent copy constructor makes that trivial.

  3. Don't do any of this. This is why, with great wailing and much gnashing of teeth in design decisions, the almighty C++ standards committees of years-gone-by have so-chosen to bless us with std::vector<>. If you're doing this to learn, good. What you'll eventually learn is how rarely you need to once you embrace the standard library and all its guilty pleasures.

If this is intended as a learning exercise, kudos, and blissfully ignore (3) above. For (2), you can use the copy/swap idiom now that you have a reasonable copy-ctor:

Array& Array::operator =(Array obj) // value-param intentional
{
    std::swap(_arr, obj._arr);
    std::swap(_size, obj._size);
    return *this;
}

Best of luck.

2 of 5
0

_size has no initial values, since you have not passed it either as arguements or initialized anywhere else before using it.

Also, don't do *_arr[i] = *obj._arr[i];

It doesn't make sense as arr[i] itself means *(arr+i).

Do:

_arr[i] = obj._arr[i];
Top answer
1 of 2
1

This is wrong on a number of levels. First in the class declaration:

char content[];

That gives you a pointer to an array of zero length.

This gives you an array of char, of zero length. This is not useful.

char* content = new char[_len];
content = _chars;

That does a new into a new variable content - not the class variable. Then you assign (overwrite) the passed pointer into content (discarding the memory you just allocated). That pointer is then discarded when the constructor ends. Perhaps using strcpy would be better.

I made up a small example based on your code which prints the correct result:

class bufr 
  {
  public:
    //constructor and deconstructor
    bufr(char* chars, uint8_t len);
    ~bufr();

    //variables
    uint8_t len_;
    char * content_;
  };    // end of class bufr

bufr::bufr(char* chars, uint8_t len) 
  {
  content_ = new char[len];
  memcpy (content_, chars, len);  // copy into allocated memory
  len_ = len;   // remember length
  }   // end of constructor

bufr::~bufr()
{
  delete [] content_;
} // end of destructor

void setup() 
{
  Serial.begin (115200);

  char chars[] = "1234 ";
  bufr buf(chars, sizeof chars);

  Serial.println (buf.content_);
} // end of setup

void loop() 
{
} // end of loop

Can you explain to me why it was making a new variable content and not using the class variable?

Small example:

char * content;

void loop ()
  {
  char * content = "foo";  // makes a NEW variable
  }

In this example there are two variables named content. The one in the function "shadows" the global one. However the code below only has one variable:

char * content;

void loop ()
  {
  content = "foo";  // uses existing variable
  }

In the destructor, when you delete the pointer to the array, does this free up the memory allocated to the array? It's now free to be assigned again by something else? Or does it sit there still initialized as that array, not being able to be used again?

You aren't deleting the pointer. You are deleting the memory it points to. The pointer is now pointing to freed memory, so using it as a pointer at this stage would be wrong. You can do another new to make it point to something else.


they delete pointer and then delete[] pointer.

You misinterpreted that. You either delete pointer or delete [] pointer depending on whether pointer is an array or not. I reworked content to not be an array, thus deleting it without the brackets is correct however as it is allocated using new [] it must be deleted with delete [].


on the link posted above they say to use delete this way: delete pointer if it was a single element allocated with new or delete [] pointer to release memory allocation for arrays of elements allocated with new and a size in []'s. So in my case I want to use delete [] content_?

No, you don't want to be setting up an array in the first place. Take a look at this small example:

struct   {
  char bar [];
  } foo;

void setup() 
{
Serial.begin (115200);
Serial.println ("Starting");
Serial.println (sizeof (foo));
Serial.println (sizeof (foo.bar));
}

void loop() 
{
}

That prints:

Starting
0
0

The variable bar is a zero-length array. Thus the entire struct foo is also zero length. It isn't even a pointer (that would be two bytes on this platform).

It is wrong to use an array of char like that, when you want to dynamically allocate memory. Look at this:

char foo [4];

That allocates 4 bytes of memory for foo. You can't later on make it longer by doing a new.

What you want is:

char * foo;

Now you have allocated a pointer and can do a new, like this:

foo = new char [10];  // allocate 10 bytes

And then delete it:

delete [] foo;

You use the brackets on the delete, as you used them with the new.

If you allocated one char you wouldn't use brackets. eg.

char * foo;
foo = new char;  // allocate a pointer to one byte
...
delete foo;
2 of 2
2

Many programmers have a disjoint between a pointer and an array. Here's an explanation.

Here is a variable of type char, initialised with the value 'A':

char c = 'A';

'A' has the ASCII value of 65, so that means that there's a byte in memory that holds the value 65. Let's say that byte in memory is at address 0x2000. If you were to add 1 to that byte, it would become 66, and if you were to print it as a character, it would print B (ASCII 66).

Here is a pointer to a char, initialised with the address in memory of c:

char *p_c = &c; // Get the address of c into p_c

[Note that char *p_c = c; would be invalid: you can't initialise a pointer with a char! That'd give p_c the value 65 - not what you want!]

In Arduino, p_c represents two successive bytes of memory that together store the address of a char: in this case the value 0x2000. Where those two bytes are doesn't matter for this explanation - but trust that they too have an address...

If you were to change c into a 'Z', that would change c's contents, but not p_c's (it would still be 0x2000). But if you were to use p_c to look at the byte it was pointing to (c), then you'd see the 'Z'.

  • If you were to do a printf("%c", c); you'd get a 'Z'.

    %c means "I've got a character as the next variable in the printf() list".

  • If you were to do a printf("%c", *p_c); you'd also get a 'Z'.
  • If you were to do a printf("%c", p_c); you'd get horrible results.

    You lied to printf() - you didn't give it a one-byte character, you gave it a two-byte pointer!

Now let's move on to arrays.

Here is a variable of type char [], initialised with the value "John".

char s[] = "John";

'J' has the ASCII value 74, 'o' 112, 'h' 104, and 'n' 111. That means that in memory there are four sequential bytes with the values 74, 112, 104, 111. Let's say that those bytes are at addresses 0x3000 through 0x3003.

And here is another pointer to char, this time initialised with the address in memory of s.

char *p_s = s; // Point to s with p_s

I hate that the C language allows the above. It is one of the roots of the whole array/pointer confusion. It kind-of implies that p_s somehow gets all of "John" assigned to it. Nope!

A better statement would have been:

char *p_s = &s; // Initialise p_s with the address of s // ILLEGAL!

That gives a MUCH better idea of what's happening - alas, it's not how it's done...

But also note that neither of the above could possibly store 0x3000-0x3003 (the addresses for all of s), so they have to be satisfied with only storing the start of the string: p_s will get the value 0x3000.

Note that s does NOT have the value 0x3000 in it. That is its address, like 0x2000 was c's address (it too doesn't have 0x2000 in it). But p_s does have 0x3000 in it - and don’t forget that p_s also has its own address (I won't bother with that here).

And this is where the "equivalency" (they're not) between a pointer and an array starts to get people confused:

  • s[2] = 'h'; and p_s[2] = 'h'; do the same thing - but in different ways!
    • The first accesses 0x3002 directly.
    • The second needs to find out that p_s is 0x3000 and add 2 to it before it can access 0x3002.
  • *(p_s + 2) = 'h'; is yet a third way to do the same thing.

So now let's printf() these new variables:

  • printf("%c", *s); wouldn’t compile.

    s is not a pointer, so you can’t dereference it with *.

  • printf("%c", *p_s); would print the character at where p_s was pointing.

    This would print out J.

  • printf("%c", s[0]); would print the character at s[0].

    This would print out J.

  • printf("%c", s); would give horrible results.

    Again, you lied to printf()!

  • printf("%s", s); would work (but see below).

    %s means "I've got a sequence of characters that I'd like you to print. I've provided the address of the first character."

  • printf("%s", p_s); would be identical to the previous one.

    After all, the same address value was passed!

  • printf("%s", *p_s); would give horrible results.

    Again, you lied to printf()!

But note something: you've given printf() the beginning of the string, so it can start printing. How does printf() know where the end of the string is? You didn't provide the number 4; it's not stored anywhere; how can it know when to stop?

That's where a C convention for strings steps in. By convention, when the compiler sees a string "between quotes", it stores the ASCII values of the characters, and then follows them with a 0. Not an ASCII '0' (with value 48), but an ASCII NUL (with value 0). Thus if you looked at address 0x3004 (the byte directly after John), you'd see a 0 in that memory byte. That's how printf() knows to stop printing - and yes, many a bug has resulted from forgetting to maintain a NUL at the end of a sequence of chars!

That then leads me to the sizeof() function

sizeof() always returns a constant at compile time using information that the compiler then knows about:

  • sizeof(c) would return 1.
  • sizeof(p_c) would return 2.
  • sizeof(p_s) would also return 2.

    It is after all merely a pointer too.

  • sizeof(*p_c) would return 1.
  • sizeof(*p_s) would also return 1.

    It's only pointing to a single char...

  • sizeof(s) would return 5.

    The compiler knows what s is: an array of 5 bytes (including the final NUL).

  • Given a pointer, there is no (native) way to find out how large the buffer it is pointing to can be.

OK: so if you've got a char [] you can find out its size. Note that that is its maximum size - the string inside it could be a lot shorter! If you did the following:

s[3] = 0; // Overwrite the fourth character (arrays start at 0)
printf("%s", s);

[Note a better version of the first line would be s[3] = '\0'; which means "store the ASCII character 0 (NOT '0')" instead of "store the number 0".]

you'd get Joh printed out. Note:

  • sizeof(s) remains 5;
  • You can't get the length with sizeof(*p_s);
  • The string inside it is only 3 characters long.

So... if you've got a string buffer, or a pointer to one, how do you know how long it is? Count the number of characters until you reach a NUL - and there's already a function to do that for you: strlen().

Which now leads to the final point about pointers: dynamic allocation of memory.

The array s above was sized by the compiler at compile time: it could count the characters, add one for the NUL, and reserve the right number of bytes. You could also have written:

char s[10] = "John";

which would have reserved 10 bytes and only initialised the first 5 of them. The following would be an error:

char s[3] = "John"; // Buffer too small!

Scarily, char s[4] = "John"; works... (The compiler says to itself "No room for the NUL?! Ah well...”) Better never pass that string to strlen() or printf() then!

What if you don't know at compile time how big a string is going to be? If you know at runtime, you can ask the system for a lump of memory from the heap - a reserved area that can have chunks taken from it and returned as required. There are two ways to do this:

char *p_b = (char *)malloc(size); // Where size is a variable
char *buffer = new char[size];    // Grab 'size' new chars

The first calls malloc(), passing in the number of desired bytes. If malloc() can give those bytes it will reserve them and return a pointer to them. If it can't it will return 0. You should always test the return value! If not, you'll corrupt things horribly...

The second uses the more sophisticated new[] syntax, which is more object oriented. Notice how malloc()'s return value needed to be turned into a (char *)? That's because it doesn't know what type of pointer it's returning, so it just picks void *. new does know, so it returns the correct type - but it still may return 0 if there's no room!

Once you've got either pointer, you use them just like p_s before. There is nothing stopping you from accessing outside the boundaries of the buffer - just like there isn't for p_s! Be careful!

Oh, and once you've finished with the lump of memory, you need to return it to the heap:

free(p_b);
delete [] buffer;

If you used malloc(), return it with free(). If you used new[], return it with delete[].

And all of the above is why they invented the String object.

It manages the memory; keeps track of the string's length; lets you access and modify individual characters; lets you resize the string as needed; and gets rid of the used memory once you're finished with it. No wonder people start to use String syntax when they see string pointers...

But Strings are only useful for chars. Arrays and pointers can be of and to anything - including Strings and (GASP!) pointers! Uh oh - here we go again...

Top answer
1 of 7
138

For building containers you obviously want to use one of the standard containers (such as a std::vector). But this is a perfect example of the things you need to consider when your object contains RAW pointers.

If your object has a RAW pointer then you need to remember the rule of 3 (now the rule of 5 in C++11).

  • Constructor
  • Destructor
  • Copy Constructor
  • Assignment Operator
  • Move Constructor (C++11)
  • Move Assignment (C++11)

This is because if not defined the compiler will generate its own version of these methods (see below). The compiler generated versions are not always useful when dealing with RAW pointers.

The copy constructor is the hard one to get correct (it's non trivial if you want to provide the strong exception guarantee). The Assignment operator can be defined in terms of the Copy Constructor as you can use the copy and swap idiom internally.

See below for full details on the absolute minimum for a class containing a pointer to an array of integers.

Knowing that it is non trivial to get it correct you should consider using std::vector rather than a pointer to an array of integers. The vector is easy to use (and expand) and covers all the problems associated with exceptions. Compare the following class with the definition of A below.

class A
{ 
    std::vector<int>   mArray;
    public:
        A(){}
        A(size_t s) :mArray(s)  {}
};

Looking at your problem:

A* arrayOfAs = new A[5];
for (int i = 0; i < 5; ++i)
{
    // As you surmised the problem is on this line.
    arrayOfAs[i] = A(3);

    // What is happening:
    // 1) A(3) Build your A object (fine)
    // 2) A::operator=(A const&) is called to assign the value
    //    onto the result of the array access. Because you did
    //    not define this operator the compiler generated one is
    //    used.
}

The compiler generated assignment operator is fine for nearly all situations, but when RAW pointers are in play you need to pay attention. In your case it is causing a problem because of the shallow copy problem. You have ended up with two objects that contain pointers to the same piece of memory. When the A(3) goes out of scope at the end of the loop it calls delete [] on its pointer. Thus the other object (in the array) now contains a pointer to memory that has been returned to the system.

The compiler generated copy constructor; copies each member variable by using that members copy constructor. For pointers this just means the pointer value is copied from the source object to the destination object (hence shallow copy).

The compiler generated assignment operator; copies each member variable by using that members assignment operator. For pointers this just means the pointer value is copied from the source object to the destination object (hence shallow copy).

So the minimum for a class that contains a pointer:

class A
{
    size_t     mSize;
    int*       mArray;
    public:
         // Simple constructor/destructor are obvious.
         A(size_t s = 0) {mSize=s;mArray = new int[mSize];}
        ~A()             {delete [] mArray;}

         // Copy constructor needs more work
         A(A const& copy)
         {
             mSize  = copy.mSize;
             mArray = new int[copy.mSize];

             // Don't need to worry about copying integers.
             // But if the object has a copy constructor then
             // it would also need to worry about throws from the copy constructor.
             std::copy(&copy.mArray[0],&copy.mArray[c.mSize],mArray);

         }

         // Define assignment operator in terms of the copy constructor
         // Modified: There is a slight twist to the copy swap idiom, that you can
         //           Remove the manual copy made by passing the rhs by value thus
         //           providing an implicit copy generated by the compiler.
         A& operator=(A rhs) // Pass by value (thus generating a copy)
         {
             rhs.swap(*this); // Now swap data with the copy.
                              // The rhs parameter will delete the array when it
                              // goes out of scope at the end of the function
             return *this;
         }
         void swap(A& s) noexcept
         {
             using std::swap;
             swap(this.mArray,s.mArray);
             swap(this.mSize ,s.mSize);
         }

         // C++11
         A(A&& src) noexcept
             : mSize(0)
             , mArray(NULL)
         {
             src.swap(*this);
         }
         A& operator=(A&& src) noexcept
         {
             src.swap(*this);     // You are moving the state of the src object
                                  // into this one. The state of the src object
                                  // after the move must be valid but indeterminate.
                                  //
                                  // The easiest way to do this is to swap the states
                                  // of the two objects.
                                  //
                                  // Note: Doing any operation on src after a move 
                                  // is risky (apart from destroy) until you put it 
                                  // into a specific state. Your object should have
                                  // appropriate methods for this.
                                  // 
                                  // Example: Assignment (operator = should work).
                                  //          std::vector() has clear() which sets
                                  //          a specific state without needing to
                                  //          know the current state.
             return *this;
         }   
 }
2 of 7
13

I'd recommend using std::vector: something like

typedef std::vector<int> A;
typedef std::vector<A> AS;

There's nothing wrong with the slight overkill of STL, and you'll be able to spend more time implementing the specific features of your app instead of reinventing the bicycle.

🌐
Medium
medium.com › @ryan_forrester_ › dynamic-arrays-in-c-comprehensive-guide-816d32f2e50e
Dynamic Arrays in C++: Comprehensive Guide | by ryan | Medium
October 22, 2024 - Dynamic arrays form the backbone of many C++ applications, offering flexible storage that grows with your data. Let’s dive into how they work, how to build one, and when to use them in real-world scenarios. Here’s a basic implementation that shows the core concepts: template<typename T> class DynamicArray { private: T* data_; size_t size_; size_t capacity_; void resize(size_t new_capacity) { T* new_data = new T[new_capacity]; for (size_t i = 0; i < size_; ++i) { new_data[i] = std::move(data_[i]); } delete[] data_; data_ = new_data; capacity_ = new_capacity; } public: DynamicArray() : data_
🌐
Pages
cpp-primer.pages.dev › book › 115-12.2._dynamic_arrays
12.2. Dynamic Arrays | C++ Primer, Fifth Edition
Like the arguments to make_shared (§ 12.1.1, p. 451), these additional arguments must be valid initializers for an object of the type being constructed. In particular, if the, object is a class type, these arguments must match a constructor for that class:C++11
🌐
Medium
medium.com › @jasonjc › making-a-dynamic-array-in-c-part-i-945e51482f2f
Making a Dynamic Array in C (Part I) | Jason J. C. | Medium
December 10, 2025 - The closest thing to simulating classes as one would have seen in Java or C++ is to create a ‘type-defining structure.’ Since we would really like a class-like container to store our little array data and stuff like that, we need to make a header file to declare and describe our implementations, and write: #ifndef DYNAMICARRAY_H #define DYNAMICARRAY_H #include <stdint.h> typedef struct dynamicArray { int64_t *values; } DynamicArray; #endif // DYNAMICARRAY_H
🌐
Medium
medium.com › @jcapona › dynamic-array-implementation-cpp-9deadaf1ba8e
A dynamic array implementation in C++ | by Jorge Cápona | Medium
February 15, 2017 - I started writing a dynamic array of integers in C. While doing so, I noticed that it would be better to write a class Array that managed the data structure, so I switched to C++. And, since we are already on C++, I decided to create a template class, so that we could manage a dynamic array of any type :). That’s my Array class; the important methods here are Array (constructor), push, pop, set, get and resize.
🌐
Quora
quora.com › Why-in-C-cant-you-declare-a-dynamic-array-of-objects-with-parameterized-constructors
Why in C++ can't you declare a dynamic array of objects with parameterized constructors? - Quora
Answer (1 of 3): The C++ standard states that each object in the array will have its default constructor called. There is no current mechanism to call each constructor with a different set of properties. Suppose you wanted to use parameters, but they would not change. That could be a default cons...
🌐
Reddit
reddit.com › r/cpp_questions › dynamic array implementation
r/cpp_questions on Reddit: Dynamic array implementation
October 25, 2021 -

I'm trying to write a dynamic array implementation of my own. This is what I have so far:

template <typename T>
class dynamic_array
{
private:
	T* data;
	int capacity;
	int size{};

	bool isFull()
	{
		return size == capacity;
	}

	bool inBounds(int index)
	{
		return (index > 0 && index < size);
	}

	void extend()
	{
		// TODO:
	}

public:
	dynamic_array(int size)
		: capacity{ size }, data{ new T[size] {} }
	{
	}

	void push(T item)
	{
		if (isFull())
			extend();
		else
			data[size++] = item;
	}

	T get(int index)
	{
		if (inBounds(index))
			return data[index];
	}

	int length() { return size; }
};

I was wondering if someone could help me out on the extend method. I was wondering if I needed to explicitly deallocate the memory that was allocated for the original data array. So in other words, I'm wondering if the extend method should look like this:

void extend()
{
	capacity *= 2;
	T* newData{ new T[capacity] {} };
	for (int i{ 0 }; i < size; ++i)
		newData[i] = data[i];

        // explicitly deallocate old data
	delete[] data;

        // point data to newData
	data = newData;
}

Or if I could simply omit the delete statement:

void extend()
{
	capacity *= 2;
	T* newData{ new T[capacity] {} };
	for (int i{ 0 }; i < size; ++i)
		newData[i] = data[i];

        // point data to newData
	data = newData;
}

Will the old data be deallocated automatically? I would think not since C++ doesn't use a garbage collector.

Top answer
1 of 11
19
No, you can never omit delete statements, you have to have one for each new you perform. Also please tell me your class has a destructor, otherwise you're just leaking memory.
2 of 11
11
You're not using a smart pointer, so with every new, there must be a delete paired with it. int capacity; int size{}; These are wrong. What does the possibility of a negative size or capacity even mean? And int does not capture the range of what an allocation can be on a given machine, that is the purpose of std::size_t explicitly, but you don't want to use that, either. What you want to use is: using pointer = T*; pointer first, middle, last; Name them whatever you want, but first points to the beginning of your allocation, middle points to one past the end of your active elements, and last points to the end of your total capacity. When middle == last, it's time to reallocate. It's much easier working with pointer arithmetic than indexes and offsets, you're mixing fewer types or different syntax. new T[size] {} This is wrong. You're allocating an array of T, which means you're calling the default constructor for every T, even for unused elements that remain in your capacity. What you want to do is use void *new(std::size_t, std::align_val_t), which will give you a pointer to an untyped byte buffer. You have to cast it yourself: first{ reinterpret_cast(new(size, alignof(T))) } And then, when you add elements to your dynamic array, you have to call placement new: void push_back(const T &value) { if(middle == last) { extend(); } new (middle++) T{value}; } Placement new will invoke the appropriate constructor. You also have to manually call the destructor and placement delete: void pop_back() { if(first != middle) { middle->~T(); delete (first, middle--); } } Are you starting to see why all pointers, all the time is kind of an awesome way of doing things? It's a higher level of abstraction. Here's how you can copy from the old buffer to the new: for(pointer i = new_first, j = first; j < last; new (i++) T{*j++}); C++ has a very, very good type system. It'd be a shame not to use it. Because we didn't call new [] on the buffer, we don't call delete [] on the buffer: ~dynamic_array() { pop_all(); // Whatever... Destroy all the elements. delete(reinterpret_cast(first)); } Here, we've matched the right delete for the buffer to the new that allocated it. Placement delete that we saw in pop_back doesn't actually do anything, but you have to call it anyway. Why? Because you can define custom new and delete operators for your types, and if those exist, you want to make sure they're called correctly.
🌐
Florida State University
cs.fsu.edu › ~myers › cop3330 › notes › review2.html
C++ Review for Test 2: List of Concepts Covered
Phonebook database example - examples of dynamic allocation, dynamic resizing of array, pass by address, destructor · Every class has these. If not user-provided, a default is built: ... Not every class has a "default constructor" (i.e.