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:

As of the time of writing, the GCC still has a bug where initializing a dynamically allocated array of chars using a C-style string literal causes a compiler error:

If you have a need to do this on GCC, dynamically allocate a std::string instead (or allocate your char array and then copy 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

408 comments to 6.9a — Dynamically allocating arrays

  • i was trying to pass the array into the sort function safely but i doesnt feel right even though this works

    • * Initialize your variables with brace initializers.
      * Limit your lines to 80 characters in length for better readability on small displays.
      * Use ++prefix unless you need postfix++.
      * You're leaking @ptr_arrayOfNames.
      * The forward declarations can be avoided my moving @main below the other functions.
      * Line 52+, 67+: Duplicate code, can be reduced to

      That's the correct way of passing an array. C++ has several list containers (covered later), which combine the array and its length so you don't have to pass them separately.

  • OmegaX128

    Hey again! How does this look for the quiz question?

    • * Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
      * Line 13: You're clearing the error flag, even if no error occurred. If an error occurred, you don't do anything about it (other than clearing the flag).
      * Line 26: Unnecessary variable. You can extract directly into an array element.
      * Sorting your includes alphabetically can help organizing your code.

      Looks good otherwise!

  • Ali Ahmad

    What if I want to find the size of a dynamically allocated array? How shall I do this?

  • MasterOfNothing

    Can anyone explain this:

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

    or allocate your char array and then copy the string in? My head is a bit spinning from pointers and arrays. How do I copy the string in again?

    QUIZ!
    I fear the do-while is unnecessary or can lead to problems here:

    • * Line 21, 40, 42, 46, 6, 65, 8, 9: Initialize your variables with brace initializers.
      * Line 9: Limit your lines to 80 characters in length for better readability on small displays.
      * Line 30, 35, 53: Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
      * Line 49: You're checking for an error, but you continue even if an input error occurred. (I don't think anything can go wrong when extracting to a string anyway).
      * Line 43: Should be a for-loop.
      * Line 65+: Use curly brackets.

      You can use @std::strcpy from @<cstring>

      • MasterOfNothing

        Thank you for the input!

        Yes, brace initializing is thing I forget, often.

        So a pure string can also be used as an argument for strcpy() function. I thought only C-style strings were accepted as both arguments.

  • Dimbo1911

    Good morning, does this code seem ok? Is it required to include string and utility? This compiles fine without it (no warnings) on code blocks 17.12 with C++17

    • Hi!

      * Use angle brackets to access arrays.
      * Line 35: Unnecessary, @wasChanged dies at the end of a cycle and is re-defined.
      * Line 51: Using the no-throw version but not checking if the allocation was successful will cause more trouble than ignoring the exception.
      * Line 59: Unnecessary, your program is done after this line.

      If you use something, include it. Your code might compile fine for you, but it might not for someone else or with a different compiler.
      Your implementation of @<iostream> includes @<string> and @<utility>. That's not standard.

  • Tom

    Hi all - I've been banging my head for the past two hours trying to work out why my sorting algorithm doesn't work, even after comparing it to the one in the solution.

    This prints "Alex Jason John Chris Mark" after it finishes running (still working on the formatting!). Otherwise, it works fine when I replace my sorting algorithm with the one found in the solution. Any thoughts?

  • Hi
    Thanks a lot for this lovely tutorial.

    I just tried out the following code on https://www.onlinegdb.com/online_c_compiler:

    This is working fine. So I just have a doubt regarding the array size of a fixed array. Doesn't this code allow us to chose any array length at runtime??

    Thanks

    • It's not valid cpp. The -pedantic-errors compiler flag should prevent this. I couldn't get onlinegdb to abort compilation.

      It's working here
      https://rextester.com/l/cpp_online_compiler_clang
      with

  • yh

    When I use dynamically allocated arrays in C++, I got this "iso c++ forbids variable length array". Does it mean we shouldn't use this style in C++?

    • It means you didn't dynamically allocate it. You did something like this

      @arr is not dynamically allocated, it's length must be known at compile time.
      What you should do is

      • yh

        Thanks! I found my problem. I was trying to dynamically allocate a 2D array like this:

        Turns out it's more complicated than I thought to dynamically allocate a 2D array, so I use a 1D array workaround at last.
        Thanks!

Leave a Comment

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