Search

6.9a — Dynamically allocating arrays

In addition to dynamically allocating single values, we can also dynamically allocate arrays of variables. Unlike a fixed array, where the array size must be fixed at compile time, dynamically allocating an array allows us to choose an array length at runtime.

To allocate an array dynamically, we use the array form of new and delete (often called new[] and delete[]):

Because we are allocating an array, C++ knows that it should use the array version of new instead of the scalar version of new. Essentially, the new[] operator is called, even though the [] isn’t placed next to the new keyword.

Note that because this memory is allocated from a different place than the memory used for fixed arrays, the size of the array can be quite large. You can run the program above and allocate an array of length 1,000,000 (or probably even 100,000,000) without issue. Try it! Because of this, programs that need to allocate a lot of memory in C++ typically do so dynamically.

Dynamically deleting arrays

When deleting a dynamically allocated array, we have to use the array version of delete, which is delete[].

This tells the CPU that it needs to clean up multiple variables instead of a single variable. One of the most common mistakes that new programmers make when dealing with dynamic memory allocation is to use delete instead of delete[] when deleting a dynamically allocated array. Using the scalar version of delete on an array will result in undefined behavior, such as data corruption, memory leaks, crashes, or other problems.

One often asked question of array delete[] is, “How does array delete know how much memory to delete?” The answer is that array new[] keeps track of how much memory was allocated to a variable, so that array delete[] can delete the proper amount. Unfortunately, this size/length isn’t accessible to the programmer.

Dynamic arrays are almost identical to fixed arrays

In lesson 6.8 -- Pointers and arrays, you learned that a fixed array holds the memory address of the first array element. You also learned that a fixed array can decay into a pointer that points to the first element of the array. In this decayed form, the length of the fixed array is not available (and therefore neither is the size of the array via sizeof()), but otherwise there is little difference.

A dynamic array starts its life as a pointer that points to the first element of the array. Consequently, it has the same limitations in that it doesn’t know its length or size. A dynamic array functions identically to a decayed fixed array, with the exception that the programmer is responsible for deallocating the dynamic array via the delete[] keyword.

Initializing dynamically allocated arrays

If you want to initialize a dynamically allocated array to 0, the syntax is quite simple:

Prior to C++11, there was no easy way to initialize a dynamic array to a non-zero value (initializer lists only worked for fixed arrays). This means you had to loop through the array and assign element values explicitly.

Super annoying!

However, starting with C++11, it’s now possible to initialize dynamic arrays using initializer lists!

Note that this syntax has no operator= between the array length and the initializer list.

For consistency, in C++11, fixed arrays can also be initialized using uniform initialization:

One caveat, in C++11 you can not initialize a dynamically allocated char array from a C-style string:

If you have a need to do this, dynamically allocate a std::string instead (or allocate your char array and then strcpy the string in).

Also note that dynamic arrays must be declared with an explicit length:

Resizing arrays

Dynamically allocating an array allows you to set the array length at the time of allocation. However, C++ does not provide a built-in way to resize an array that has already been allocated. It is possible to work around this limitation by dynamically allocating a new array, copying the elements over, and deleting the old array. However, this is error prone, especially when the element type is a class (which have special rules governing how they are created).

Consequently, we recommend avoiding doing this yourself.

Fortunately, if you need this capability, C++ provides a resizable array as part of the standard library called std::vector. We’ll introduce std::vector shortly.

Quiz

1) Write a program that:
* Asks the user how many names they wish to enter.
* Asks the user to enter each name.
* Calls a function to sort the names (modify the selection sort code from lesson 6.4 -- Sorting an array using selection sort)
* Prints the sorted list of names.

Hint: Use a dynamic array of std::string to hold the names.
Hint: std::string supports comparing strings via the comparison operators < and >

Your output should match this:

How many names would you like to enter? 5
Enter name #1: Jason
Enter name #2: Mark
Enter name #3: Alex
Enter name #4: Chris
Enter name #5: John

Here is your sorted list:
Name #1: Alex
Name #2: Chris
Name #3: Jason
Name #4: John
Name #5: Mark

Quiz solutions

1) Show Solution

6.10 -- Pointers and const
Index
6.9 -- Dynamic memory allocation with new and delete

307 comments to 6.9a — Dynamically allocating arrays

  • ayush

    an error is there
    33    25    C:\Users\ayush\Documents\cpp\a25.cpp    [Error] cannot convert 'std::string* {aka std::basic_string<char>*}' to 'int*' for argument '1' to 'int sortarray(int*, int)'

    how to resolve this

    and kindly tell me more about this program plzzzzz
    im trying my best to understand this but i cant

    • Idda

      hi ayush,
      in row 5:  int sortarray(int *array,int
      length)
      row 26:string *names=new string[length];
      and
      row 33: sortarray(names, length);
      ==> change the datatype in argument in row 5
      I guess it'll solve the problem!
      ...and one more thing...you should try to use std::namespace in place of "using namespace std"

  • Rohit

    So I forgot to #include <utility> but the "swap" function still worked. So I checked and apparently in VS 2017, utility is one of the precompiled files in the "External Dependencies" folder in the Solution Explorer pane.

    What confused me though is in a new solution, "string.h" is also there but I still have to #include <string> to get strings to work. Including that adds "string" next to "string.h". Am I correct in thinking that all those files ending in ".h" are ported from c and the ones without .h are c++ versions only?

    I still don't know why I would need to #include <string> if string.h is there and why string.h would be there if i'm required to #include <string> regardless?

    Now the code:
    i know i should use <limits> instead of 32767, but when i gotta do it like 5 times i get lazy haha.
    Also, would it be better to create the array in a different function and then pass the pointer to main or is creating it in main like i did perfectly fine?

    • Alex

      > Am I correct in thinking that all those files ending in ".h" are ported from c and the ones without .h are c++ versions only?

      No, the ones that end in .h are the ones that don't use have their names in the std namespace.

      The headers ported from c generally start with a c (e.g. cassert, cmath, etc...)

    • nascardriver

      Hi Rohit!

      > when i gotta do it like 5 times i get lazy
      Having to write something 5 times is an indicator for having to write a wrapper function for it.

      Suggestions:
      * Line 35: Initialize strings to "".
      * Line 44: Should be currentName[0], because you only care about the first character.

      Creating the array in @main is fine, you'll learn about alternatives to dynamic arrays in a couple of lessons.

      • Rohit

        Fair point about the wrapper function. what exactly is a wrapper function? would it be kind of like my @printNames function in the sense that i can call it to do the same thing over and over?

        On line 35 i meant to initialize currentName to "\0"; i don't even know how i wrote "\n". guess i'm just so conditioned to type the newline indicator whenever i have a backslash lol

        And good point about line 44. strangely enough though, the comparisons and sorting still work even if i don't use [0]. i guess std::string instinctively knows that comparisons should be defaulted to the first character

        • nascardriver

          A wrapper function is a short function that allows easier access to something else without adding new functionality.
          @std::string::operator< performs a lexicographical comparison on the two strings, but since you only care about one character this is a waste of resources.

  • nascardriver

    Hi Endcity!

    "For standard strings this function performs character-by-character lexicographical comparison."

    References
    * std::basic_string::compare -https://en.cppreference.com/w/cpp/string/basic_string/compare

  • Endcity

    What does the comparation between 2 string that be used in quiz sollution to sort string array alphabetical work ?

Leave a Comment

Put all code inside code tags: [code]your code here[/code]