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.

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

233 comments to 6.9a — Dynamically allocating arrays

  • DOG_TRAINER

    You said b4 that we need to use this, so our program doesn’t skip over after asking for a number then a string, but yours didn’t skip at all.

    Here’s my code: What do you think? Thank you.

  • Kushagra

    Why can’t we use std::getline to get names?
    what about getting sirnames  with std::cin?
    didn’t it put the sirname to the next std::cin ?

    • Alex

      > Why can’t we use std::getline to get names?

      You can, like this:

      > what about getting sirnames with std::cin?

      std::cin and operator<< break on whitespace. So you’d have to keep reading until you hit a newline and concatenate the results. If you want to do this, just use std::getline.

      • Kushagra

        using std::getline is causing run time error.
        name 1 is printed. without asking anything it also prints name 2 , then it asks about entering name

        • Alex

          Can you post your code snippet that’s not working?

          • Kushagra

            Your snippet is doing the same problem.

            #include <iostream>
            #include <string>
            #include <algorithm>

            void sortArray(std::string *array, int length)
            {
                // Step through each element of the array
                for (int startIndex = 0; startIndex < length; ++startIndex)
                {
                    // smallestIndex is the index of the smallest element we’ve encountered so far.
                    int smallestIndex = startIndex;

                    // Look for smallest element remaining in the array (starting at startIndex+1)
                    for (int currentIndex = startIndex + 1; currentIndex < length; ++currentIndex)
                    {
                        // If the current element is smaller than our previously found smallest
                        if (array[currentIndex] < array[smallestIndex])
                            // This is the new smallest number for this iteration
                            smallestIndex = currentIndex;
                    }

                    // Swap our start element with our smallest element
                    std::swap(array[startIndex], array[smallestIndex]);
                }
            }

            int main()
            {
                std::cout << "How many names would you like to enter? ";
                int length;
                std::cin >>length ;

                // Allocate an array to hold the names
                std::string *names = new std::string[length];

                // Ask user to enter all the names
                for (int i = 0; i < length; ++i)
                {
                    std::cout << "Enter name #" << i + 1 << ": ";
                    std::getline(std::cin , names[i]);
                }

                // Sort the array
                sortArray(names, length);

                std::cout << "\nHere is your sorted list:\n";
                // Print the sorted array
                for (int i = 0; i < length; ++i)
                    std::cout << "Name #" << i + 1 << ": " << names[i] << ‘\n’;

                delete[] names; // don’t forget to use array delete
                    names = nullptr; // use 0 if not C++11

                return 0;
            }

            • Alex

              Oh. You need to make sure you ignore the ‘\n’ in the stream, like this:

              Otherwise the first call to std::getline() will read the \n and treat it as an empty string input.

  • Kushagra

    Instead of this answer of quiz , can’t we rearrange names just similar to arranging integers like this

    #include <iostream>
    #include <algorithm>
    #include <string>
    int main()
    {
        std::cout << " How many names do you want to write ?" << std::endl;
        
        int length ;
        std::cin>>length;
        std::string *block = new std::string[length];
        
        for (int a = 0; a<length; a++)
        {
            std::cout << " name " << (a+1) << " is : ";
            std::cin >> block[a];
        }
        for (int g = 0; g<length; g++)
        {
        for ( int x =0; x<(length-1); x++)
        {
            if (block[x] >block[x+1])
            std::swap(block[x] , block[x+1]);
        }

        
        }
        
        std::cout << " The sorted order is " <<std::endl;
        
            for (int y = 0; y<length; y++)
        {
        std::cout << "name  " << (y+1) << " is :   " << block[y] <<std::endl;
        
        }
        delete[] block;
        block = nullptr;
        return 0;
    }

  • Frodo

    How can std::cin >> names[i] be altered so that std::cin.getline() is used?

  • JRCS

    I seem to have got into the habit of putting everything in functions if I can, so this code looks quite different to your solution. It still works, so that’s cool, I suppose.

    • Alex

      Yup, that’s great! Your code is nicely organized. A few minor things:
      1) Using a global “using namespace std” is frowned upon
      2) You don’t need to set name to 0 after deleting it (it’s going to go out of scope and get destroyed immediately anyway)

  • chathura

    Oh thx for that it did help.

  • chathura

    Hi i just have a small problem with sortArray method. How does it sort the string alphabetically i’m bit confused because i understand the concept if they were numbers. please help.

  • Eric

    I have a question about the sorting function. When sorting, is it doing it by the ascii value, because i was playing around and mixing capitalization and lowercase and it appears to be arranging by those values. What would you suggest be the most optimal way to correct this? As an example run a check and convert everything to be uniformed (capitalized or all lowercased).

    • Alex

      Yes, if you’re sorting characters, it will do so by ASCII value. You can fix this by converting everything in your source array to use uniform capitalization. But a better idea is to modify your sort to deal with inconsistent capitalization (so caps gets temporarily converted to lower case before the comparison happens). That way, your source array can remain unmodified.

  • Angmar

    Hi Alex, thanks for your prior helps. I have another question.

    So the

    operator returns a pointer, right? Is it possible to dereference them with the

    operator? I was trying to build a string array and each of the following fails to build:

    I’d be very grateful if you explain why 1,2, and 6 won’t work

    • Alex

      When you dereference a pointer that is pointing to an array, you get the value of the first element.
      1) Doesn’t work because you’re trying to initialize your names array with a single value. This causes a type mismatch.
      2) Direct initialization doesn’t work with arrays, which is one of the reason uniform initialization was created.
      6) This is a confusing case. string names[] defines a string array (not a string pointer). new string[count] returns a pointer. C++ won’t let you convert a pointer into an array.

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter