newbie
newbie

Reputation: 35

how to correctly use a dynamic array?

So I am trying to use a dynamic array for my program and I do not know if I am doing it right. Should I use const int or just an int only?

int size = 1;
    int *num1 = new int [size];
    int *num2 = new int [size]; 

or

const int size = 1;
        int *num1 = new int [size];
        int *num2 = new int [size]; 

Upvotes: 1

Views: 81

Answers (2)

Some programmer dude
Some programmer dude

Reputation: 409482

If the size is a compile-time constant that you want to create an "array" from, then I suggest std::array, as in

std::array<int, 1> num1;

If the size isn't known at compile-time then use std::vector, as in

std::vector<int> num1(size);

And if you really have to use explicit dynamic allocation then opt for smart pointers like std::unique_ptr, like

auto num1 = std::make_unique<int[]>(size);

As for if the variable size should be const, constexpr, not qualified at all, or if you should possible use the literal value directly when allocating, then it really depends on use-case, value availability, and personal preference.

On another note, for a size you should rather use the size_t type instead of int. Most programmers will immediately understand that when you use size_t the variable is used to store a size. Otherwise if you use int it could be any arbitrary integer value. Furthermore, size_t is an unsigned type, so it doesn't allow negative numbers, which is one less cause of problems.

Upvotes: 6

JohnFilleau
JohnFilleau

Reputation: 4288

I've seen you ask a few questions about this now, so I want to show you the difference between having to resize a dynamic array and using std::vector, which packages all of the features you'd want in a dynamically-sized block of contiguous memory.

The following code is how to increase a dynamic array to hold user input. We don't know how long the user wants to input numbers for, so we have to keep resizing every time they enter a new number.

int number = 0;
std::size_t array_size = 0; // we need to track the size of the thing
int *array = nullptr; // nothing in here yet

std::cout << "Enter a number, non-number to exit: ";
while (std::cin >> number)
{
   // we need to request more memory
   ++array_size;
   int *new_array = new int[array_size];

   // we have to copy the old array to the new array
   // fun note: as pointed out in the comments below, using memcpy on
   // either src or dest == nullptr is undefined behavior. Just goes to
   // show how hard it is to get something like this correct.
   // Don't do this when we have perfectly good STL containers!
   std::memcpy(new_array, array, (array_size - 1) * sizeof(int));

   // delete the old array, if it exists (we can safely call delete on a nullptr)
   delete[] array;

   // assign the new block of memory to array
   array = new_array;

   // add the retrieved element to array
   array[array_size - 1] = number;

   std::cout << "Enter a number, non-number to exit: ";
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

// output the array
for (std::size_t i = 0; i < array_size; i++)
{
    std::cout << array[i] << "\n";
}

// all done, delete the memory that was allocated
delete[] array;
array = nullptr; // not strictly required, but can prevent us from accidentally deleting the same block of memory twice, which would be bad

We can do the same thing using std::vector:

int number;
std::vector<int> vec; // this is a vector that holds ints, it tracks its own size and memmory

std::cout << "Enter a number, non-number to exit: ";
while (std::cin >> number)
{
    vec.push_back(number); // all done

    std::cout << "Enter a number, non-number to exit: ";
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

for (std::size_t i = 0; i < vec.size(); i++)
{
    std::cout << vec[i] << "\n";
}

// or we can used range-based for loops, which are awesome
for (auto& v : vec)
{
    std::cout << v << "\n";
}

Note that in the std::vector example, I'm outputting the contents of the std::vector twice, just to show that we have an option for iterating through a vector that is not available for an int *. We don't need to keep track of memory. We don't need to new and delete. When the current program scope exits (if this is a function, for example), the destructor of the std::vector is called and cleans up memory for us.

USE VECTORS!!!

Upvotes: 1

Related Questions