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:

However, this was fixed in C++14.

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

215 comments to 6.9a — Dynamically allocating arrays

  • Aymen

    Hi Alex, just managed to figure out how to fix my sort code and I needed to add +1 on the second for loop.

    Why has that worked when in previose scenarios I did size-1 on the first for loop and size-1 in the second for loop and it worked, why is this time any different?

    Cheers

    • Alex

      This is something you should answer for yourself. Pick a small array (e.g. size 4) and go through the code in both cases until you’re convinced you understand how it’s working.

  • hei_xhimi

    Thakns Alex,i just noticed it!!!

  • hei_xhimi

    Hi Alex, I tried the quiz and i wrote the following code:

    the problem is it stops executing after the names are entered.
    2)i want also to ask about the "auto" you are using in the for_loops ,why not simpli use "int"?
    when i tryed "auto" the comlpiler showed the following errors:
    error:"count" does not name a type;

    • Alex

      This would be a good problem to debug. You’d discover that function sortInput() is going into an infinite loop.

      It’s because you are incrementing sizeArray instead of startIndex or currentIndex.

  • Kodnot

    Hey Alex. First of all, thank you for an amazing tutorial. It’s been a lot more helpful to me than any of the "C++ for beginners" books I’ve read.
    Now, I have 2 questions:
    1. What’s the difference between this:

    and this:

    , if any? As far as I can tell, both of these initialize the array to 0’s. If I were to initialize a static array, I’d use {}. So why should I use ()?

    2. You mentioned vectors. I know that you’ll probably explain everything in the later chapters, but I’d still like to know: in what situations would you prefer dynamically alocated array over std::vector? Everywhere I’ve read, it seems like people say that vectors should always be used instead of dynamic arrays, is that true?

    Ps. A third question, though it might be a bit out of place. I am using Code::blocks. As far as I know, getline() belongs to std namespace. So why can I use it without the std:: prefix? The part that is the most confusing to me is that this only applies for this function (If I, let’s say, try to declare a string without the std::, I get an error).

    • Alex

      1) They are identical, except I think the curly brace method only works in C++11 (it was introduced as part of uniform initialization).
      2) Yes, you should almost always use std::vector over dynamic arrays, because they are safer and self-deallocate when they go out of scope. The only use case I can think of for using dynamic arrays instead is when you need precise control over how much memory and when memory is allocated or deallocated. std::vector may allocate more memory than you ask for.
      3) I am not sure. I see the same thing in Visual Studio. Something is exposing it outside of the namespace, but I’m not sure why. Perhaps for backwards compatibility.

      • This is a great introduction to handling dynamically allocated arrays and understanding how C++ works internally. However, I do think you could stress that std::vector is a _much_ better alternative to allocating the arrays using new[] already in the beginning of the article. Everyone who starts to learn C++, from your site or anywhere else, are early on taught to use dynamic arrays and allocating the memory they need using new[] (or new without brackets also for that matter). This creates the problem that people start using this pattern when writing C++ professionally, creating problems with memory management and giving the impression that C++ is a difficult language to use because you always have to remember to "delete what you new". If students were taught to use the standard library containers and algorithms from an earlier stage I think we would have less problems with error prone C++ code which crashes and leaks memory.

        See e.g. the C++ core guidelines on new and delete:  https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es60-avoid-new-and-delete-outside-resource-management-functions

        Or my own site: http://www.moderncplusplus.com/

        Thank you!

        • Alex

          I have a lesson on std::vector later in this chapter, which includes information about why std::vector is a better choice.

          I believe it’s good to know how all of this dynamic memory stuff works, because even if you never write it yourself, you’ll likely run into code that uses it. And std::vector isn’t appropriate for _every_ use case.

  • Ran

    Hi Alex:

    Following is my code. I spent two days to figure out this problem. It was hard for me, but finally I made it!

    After I done my work, I checked my code with yours. I could not believe that I almost have the same code with you!

    Thanks for your great tutorial!

  • Sol

    Here’s mine but I’m kind of confuse on what pointer does. In line 9.

    • Alex

      My code dynamically allocates an array from the heap. This array will live until it’s deleted using the delete keyword.

      Your code statically allocates a local fixed-size array. This array will live until it goes out of scope, at which point it will be automatically destroyed.

      • Sol

        What’s the use of deleting an array before it goes out of scope? Just memory reasons? If so, is it for optimization or is it a must for writing programs? Thanks.

        • Alex

          If you dynamically allocate an array, that array sticks around until you delete it. If the pointer holding the memory address of the dynamically allocated memory goes out of scope, then you have no way to reference that memory any more, and the memory is lost (this is called a memory leak).

          Deleting a dynamically allocated array allows you to return the memory back to the operating system so it can be reused.

          Basically, with fixed arrays, the program handles the allocation and deallocation for you. With dynamic arrays, you handle the allocation and deallocation. This gives you a lot more flexibility, but comes with the cost of having to remember to do the deletion or risk a memory leak.

  • Arda

    Hey Alex! My program doesn’t work properly. Can you take a look at it please and tell me what’s wrong with it?

    And here’s the output of the program.

    How many names do you wish to enter?
    5
    Enter name #1:Enter name #2:James
    Enter name #3:Reus
    Enter name #4:Diana
    Enter name #5:Glenn
    Here is your sorted list:
    Name #1:
    Name #2:Diana
    Name #3:Glenn
    Name #4:James
    Name #5:Reus
    Press any key to continue . . .

  • Chris

    Hi Alex,
    I have few questions for the quiz. this is my code.sorry for my bad English.

    1. why you include string header? I didn’t do that and work well.

    2. I didn’t  declare the pointer in main function but in names function. I delete the pointer like that, is it right?(but it’s work)

    3. why I must use string type for declare the pointer? in my opinion, this will be work(with changing the return type of names function and sorting function and any else related to that pointer) because the pointer just hold the address of array so it is up to me which type I want to declare the pointer but it is doesn’t work

    the build messages:
    ||=== Build: Debug in 6.9a (compiler: GNU GCC Compiler) ===|
    D:\Eldon\CBProjects\6.9a\main.cpp||In function ‘int* names(int)’:|
    D:\Eldon\CBProjects\6.9a\main.cpp|18|error: cannot convert ‘std::string* {aka std::basic_string<char>*}’ to ‘int*’ in initialization|
    ||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

    • Alex

      1) I included the string header because I used std::string. It may work without it (if something else you’ve #included #includes it), but you shouldn’t expect that.
      2) No. When you return namesArray, the function ends at that point. Any code after that statement never executes.
      3) C++’s strong typing system requires it, so that when you dereference the pointer, it knows what type of value to produce. e.g. if you did int *namesArray = new string[size];, what type would namesArray[1] produce?

  • Sid

    Alex,

    In the quiz solution, you have a sortarray function with two parameters. However the function is of type void which means that there is no return type. So how come you get the sorted array from the function call and then print it ? You should have a way to return the sorted array back to the main function, right?

  • pisces

    Unlike a fixed array*

    Typoo, second sentence.

  • Hridayesh Sharma

    For thecode given below which is a little modification of your code. can you please tell me why it is not showing any error even if i input size less than 10. I am not able to understand why the part of code after for loop works fine.

    • Alex

      Why are you expecting it to produce an error?

      Operator[] doesn’t do any range checking, so if you enter a size less than 10, array[10] will end up returning the value at some memory address not owned by the array. Since you’re changing that value, your program could behave unexpectedly.

  • Rob G.

    Hi Alex, my code below is all pointers and as compartmentalized as I could get it. What was really cool is that I had the code built-out for integers, and all I did was substitute string types for ints, make a string array, etc. My question -> I can call every function by passing the array to the function( swap_it, input_names, read_back_names, sort names). But in order for this to work I have to initialize the array in main.cpp. This was not a problem, but if I had several arrays to work with main.cpp would be bloated. How is this handled if you are using several arrays?

    • Alex

      You could write a function called init_array() that asks the user how many names they want, allocates the array, and then calls input_names. The function would pass back the initialized array as a pointer to the caller (in this case, main()).

      That way, you could do something like:

  • #include <iostream>
    #include <string>

    void sortName(std::string *names, int nName)
    {
        for (int startIndex=0; startIndex < nName; ++startIndex)
        {
        int smallestIndex = startIndex;
           for (int currentIndex = startIndex + 1; currentIndex < nName; ++currentIndex)
        {
            if (names[currentIndex] < array[smallestIndex])
            smallestIndex = currentIndex;
        }
        std::swap(names[startIndex], names[smallestIndex]);
        }
    //    return 0;
    }

    int main()
    {
        int nName;
        std::cout << "How many names would you like to enter? ";
        std::cin >> nName;
        std::string *names = new std::string[nName];

        for (int iii=0; iii<nName; ++iii)
        {
        std::cout << "Enter name #" << iii << ": ";
    //    std::getline (std::cin,  names[iii]);
          std::cin >> names[iii];
        }
        
        sortName(names, nName);
        std::cout << "Here is your sorted list:";
        
        for (int iii=0; iii<nName; ++iii)
        std::cout << "Name #" << iii << ": " << names[iii];
        
        delete[] names;
            names = 0;

        return 0;
    }

    I use the above code and it gives me the following error:

    main.cpp: In function ‘void sortName(std::string*, int)’:
    main.cpp:11: error: ‘array’ was not declared in this scope

    Can you help? Thanks.

  • Lucas

    Hey Alex, thanks for your excellent tutorial so far!

    Well, I’ve tried to "improve" your solution of the Quiz to accept both name and surname of the person

    i.e :

    Here is your sorted list:
    Name #1: Alex SOMETHING
    Name #2: Chris SOMETHING

    I’ve coded the following function to assign strings to each component of a string array:

    However, some weird thing is happening when using the uncommented line. Somehow the program always ignores the first input. For instance, if size is 2 this function reads nothing, if size is 2 it reads 1 input and so on.
    Then the output of the program, when size is 3,  is like this:

    Here is your sorted list:
    Name #1:
    Name #2: Alex Something
    Name #3: Julia Something

    • Alex

      Normally when you see something like this, it means you have input stuck in the stream. In this case, when you enter the number of names and type “2”, it actually puts “2\n” in the stream. Then, you read the 2 into an integer, but the “\n” is still in the stream. This gets read into your first input.

      The solution here is to discard the “\n”, which you can do using the ignore function:

      • K750i

        Pardon me if I’m wrong but I find the following does the same thing, and easier to understand:

        PS. Mainly because of that number argument that really bothers me.

  • soumya

    If pointer to a dynamic array does not know the size of the array it points to, then how come while deleting that array , it comes to know the size of the array?

    As you said that dynamic array created using array version of new operator must be deleted using array version of delete operator  , where mentioning the array size is also optional  then how does it come to know the size of the array to be deleted ?

    • Alex

      Great question. The short answer is “metadata”. When you allocate an array using new, the allocator stores some metadata indicating how long the array is that can then be used by array delete. It’s unfortunate that this information isn’t accessible by the program itself.

      • soumya

        So that means ..the size that we provide while allocating the array dynamically , from there it comes to know the length of the array while deleting it . That is what you are calling as. " metadata " ! Am I right?

        • Alex

          I think so, if I understand what you’re saying.

          When you call new with an array, compilers normally do one of two things:
          1) Allocate extra memory to store the size along with the object.
          2) Store the size in a table, using the address as a lookup value.

          That way, when you call array delete, it can access the size of the object so it knows how much memory to return to the OS.

  • deepu

    Thank you for coming up with this awesome tutorial . I don’t know why, but the program that I wrote and the solution provided to the quiz don’t work every time (the list is not always alphabetical ). I am using Code blocks . Is there any alternate method .
    Note: All the inputs either started with a lower case or upper case letter .

    • Alex

      Yeah, that’s because lower case letters have higher ASCII values than lower case letters, so it sorts A-Z and then a-z.

      If you use consistent capitalization it should work fine.

      The easiest way to fix this in code would be to capitalize or lower-case each of the names before comparing in the sort routine, to make the comparison case-insensitive.

  • Mr D

    In the quiz, I’m having a hard time getting my head around:

    So when the program compiles, "std::string *array" is just a string pointer that doesn’t point to anything?
    But during runtime, int main() passes in "names" as the first argument to sortArray, and only at THAT moment sortArray knows that "array" is actually an array?

    Am i on the right track?

    But in this case does it HAVE to be a pointer? Why couldn’t you have initialized an array as the first input to
    sortArray? I mean, aren’t all arguments that get passed into functions "dynamic" and often unknown before runtime?

    Or is the reason this is done so that no memory is allocated until the moment that sortArray instantiates the array in order to work through the rest of the function?

    • Alex

      You are correct.

      > But in this case does it HAVE to be a pointer?

      Well, you could pass in a pointer to a std::string instead of an array, but that’s not what the function intends (and unless you also passed in a length of 1, bad things will happen when you try to take the subscript of your pointer…

      > Why couldn’t you have initialized an array as the first input to sortArray?

      I’m not sure what you mean here.

      > I mean, aren’t all arguments that get passed into functions “dynamic” and often unknown before runtime?

      Not really -- the types of all the parameters are known, it’s simply the value of the arguments that’s not known until runtime.

      > Or is the reason this is done so that no memory is allocated until the moment that sortArray instantiates the array in order to work through the rest of the function?

      sortArray() doesn’t do _any_ instantiating. It simply takes an array as a parameter, and sorts the elements. The function is set up this way so we can pass _any_ array of std::string to the function, and it will sort it. This makes the function extremely reusable, as it makes no presumptions about where the array came from, what’s in it, or what the programmer intends to do with it after it’s sorted.

  • Mr D

    A question about quiz: the algorythm driving the std::string comparison seems a little odd.

    If i enter:

    length = 3
    name#1 = a
    name#2 = b
    name#3 = X

    it sorts it:

    1) X
    2) a
    3) b

    Presumably because "X" is capitalized.

    A question: is it possible to view the actual the source code of the algorhythm driving that std::string comparison? Presumably it’s written in C++, but how do i view it? Maybe i can tweak it to ignore a capital letter (as an experiment)?
    I’m using Visual Studio Community 2015.
    Thanks!

    • Alex

      It sorts based on ASCII code, and ‘X’ has a lower ASCII code than ‘a’ so it gets sorted first.

      I don’t think it’s possible to view the source for the comparison. Instead, if you want to do a case-insensitive comparison, your best bet is probably to write your own case-insensitive string comparison function (instead of using the builtin > operator). You can use the tolower() function to “normalize” each character to ensure everything is treated as lower case.

  • Rajender

    When i am trying to use getline command to enter names with spaces, I am not able to give first name as for first iteration it won’t take any input ?

  • Anonymous

    On the quiz, in main (2nd for loop), I think it should be "i+1" instead of just "i" in the cout statement. Otherwise, it would print the numbers starting from 0.

  • In the quiz solution, you forgot to null the dynamically allocated array 🙂

  • Nick

    Didn’t know you could just compare strings, thought you’d have to compare every character in the string…

    Super messy but it works!

  • Alex, needed your help:

    1. In the quiz solution (Thanks for that quiz), according to question, the 16th line will evaluate as
    if("Mark" > "Jason"), right? This evaluates to false. Why? How does string literals are compared?

    2. Why the first parameter of function sortArray() is given the type "string*". I know there is a very good reason behind that, but "string array[]" works just fine. How string* is better than string[] in this case?

    Thanks 🙂

    • Alex

      1) “Mark” > “Jason” should evaluate to true. Make sure you have the first letter properly capitalized for both names. Strings compare based on ASCII value, and “M” > “J”.

      2) “std::string *array” and “std::string array[]” are identical when used as function parameters. Personally I like using “std::string *array” because it reminds me that a fixed array will decay if passed in.

  • Typo:
    " You can run the program above an(‘d’ is missing) allocate an array of length 1,000,000 (or probably even 100,000,000) without issue."

    Suggestion:
    One thing, you should add a code example where user is given the power to set the size of the array and also the value for each of its elements.

    I am thinking of a case where programmer attempts to solve matrix problems. In this case, he has to allow the user to define all the values of the multidimensional array

    Question: Don’t we need to set the array pointer to nullptr after deallocating it, or dangling pointer never results in case of arrays?

  • Ayman

    why this code cause memory leak?

    • Alex

      This line of code:

      means both pointers are now pointing at the 30 characters allocated to str1.

      So when you delete str2, you’re actually deleting the 30 characters.
      When you delete str1, you’re trying to delete it again.

      So two problems here:
      * The 40 characters originally allocated to str2 never gets deleted (memory leak).
      * The 30 characters originally allocated to str1 gets deleted twice. This will yield undefined behavior (possibly an application crash).

  • Metereo_Rex

    I’m having a bit of confusion with this:

    If that’s ‘illegal’, then why does it compile anyway? It even returns the proper ‘sizeof()’ value relative to what I enter.

    I am starting to get the gist of this, but it’s more confusing when the issue it’s meant to solve doesn’t exist.

  • steve

    I dont know if this is a recent change, but the lengths of arrays do not need to be constant like you said at the top.

    You can cin >> arraylength and then declare the array.

    • csvan

      Steve, this is a compiler question. For example, I believe GCC allows you to do that (declare arrays using a variable), however VS for example, as far as I know, allows no such thing.

      As far as the C++ standard is concerned, I am not sure what is technically correct, but beware that this difference exists!

      Keep coding. Use it for good 🙂

  • Algernon

    #include
    #include

    void main()
    {
    clrscr();
    int *ptr;
    int n=20;
    ptr=new int[n];
    ptr[5]=7;
    ptr[6]=9;
    cout<<ptr[5]<<” “<<ptr[6]<<” n”;
    delete[] ptr;
    cout<<ptr[5]<<” “<<ptr[6];
    getch();
    }

    cant seem to understand…even after i use the delete function the values of ptr[5] and ptr[6] are still displayed….

    • csvan

      I believe this is because delete[] only releases the memory referenced by ptr, it does not destroy the information already stored in them. That is why you can still view them, as ptr still stores the same memory address, and the data you defined before still resides in those very same addresses.

      However, you should ask somebody who knows this better!

      • Alex

        Deallocating memory does not clear the memory contents, so whatever you put in there before deallocation may still be there after deallocation. But there’s no guarantee.

  • Pathik

    How do you dynamically allocate a multidimensional array?

    This does’nt work:

    • It’s a real pain to do. First allocate an array of pointers to your data type. Then loop through each element of your array and allocate an array from the pointer. Something like this (and forgive me if this is slightly incorrect since I’m doing it from memory:

      An easier way is to allocate a single-dimensional array, and then use a function to index it (again, from memory, so forgive any mistakes):

  • afds

    How do you find the size of an array with dynamically allocated memory?

    This doesn’t work.

    • afds

      I found a way…but please tell me another way if it is easier.

      • When it comes to dynamically allocated arrays in C++, you have to save the size independently of the array. There’s no way to derive it from the array, unfortunately.

        The sizeof(anArray) / sizeof(anArray[0]) trick only works if anArray is a fixed array (eg. declared as int anArray[5]) AND the array hasn’t decayed into a pointer.

        Your algorithm doesn’t really work because you loop on the size of the array, which presumes you already know it. If you already know it, there’s no reason to go through the whole process of trying to find it. 🙂

Leave a Comment

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