8

assume that we created dynamically allocated memory such as:

int SIZE = 10;
int *p = new int[SIZE];
for(int i = 0; i < SIZE; ++i)
  p[i] = i;

it will assing 0 to 9 to our pointer array.
Then i wanted to add 10,11,12 to the array
can i do :

p[10] = 10;
p[11] = 11;
p[12] = 12;

or should i do:

delete[] p;
size = 13;
p = new int[SIZE];
for(int i = 0; i < SIZE; ++i)
  p[i] = i;
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
M.SEL
  • 113
  • 8
  • 13
    Since this is `C++`, why don't you use a `vector` directly? – Tanveer Badar Nov 18 '19 at 14:16
  • 1
    That's nowhere near helpful. I think if the question involved using an array, that advice is good as an "also ..." side answer, but this question is very specificly about dynamic arrays. SO is earning its stereotype right now. – sweenish Nov 18 '19 at 14:19
  • 1
    To resize an array you have to allocate a new array and copy the old elements to the new array, then delete the old array. https://stackoverflow.com/questions/42238712/change-array-size-c – mfnx Nov 18 '19 at 14:19
  • 1
    No, you can't append to an array by writing out of bounds. You have to create a new one. Unless you want some practice on `new`/`delete`, use a `std::vector`. – HolyBlackCat Nov 18 '19 at 14:19
  • 4
    @sweenish -- The comment section is for comments, not answers. I see nothing wrong with commenting on why `vector` is not used. – PaulMcKenzie Nov 18 '19 at 14:19
  • You must resize your array of course; otherwise you'll overflow it. – machine_1 Nov 18 '19 at 14:20
  • 1
    @PaulMcKenzie Comments are for seeking clarifying information, and shouldn't be used for throwaway advice that is unrelated to the question. I feel that advice is unrelated because this is a very specific question about dynamic arrays. Students learning data structures need to know how to use them properly, so just blanket recommending a vector whenever a C-array is seen is just getting ridiculous. – sweenish Nov 18 '19 at 14:23
  • @mfnx: In C++, is there no immediate way to reallocate, similar to realloc() in C? – machine_1 Nov 18 '19 at 14:24
  • 3
    @machine_1 - Only if the memory has been allocated using `malloc()`, `calloc()`, `realloc()`. But usage of those functions (from C) is discouraged in C++, for various reasons - in particular, it gives undefined behaviour is used to allocate memory for C++ class types that have a non-trivial constructor or destructor. – Peter Nov 18 '19 at 14:27
  • @PaulMcKenzie That's a bold assumption, and a poor way to justify it. It's not like I said to never recommend vectors. I think the blanket recommendation at the sight of a C-array with no attempt at the real question is never helpful, comment or no. Just look at Mark Ingram's answer as something I believe to be an appropriate way to do this. – sweenish Nov 18 '19 at 14:27
  • 1
    @machine_1 no, neither there should be. A realloc() would do just that: reallocating the memory. But in C++ there are more things to do, like calling the destructor on the old object. – UniversE Nov 18 '19 at 14:28
  • @machine_1 You can use realloc if you please. As far as I know there is no equivalent in C++. I think "using std::vector" is a very good suggestion here. – mfnx Nov 18 '19 at 14:30
  • @sweenish No it is not a bold assumption. There have been many posts where the programmer was not aware of vector, or `std::list`, or some other C++ class or function, and were grateful that it was introduced to them in the comment section as a "why aren't you using x"? – PaulMcKenzie Nov 18 '19 at 14:47
  • @sweenish Ever heard of [xy problems](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)? – Aconcagua Nov 18 '19 at 15:05
  • @PaulMcKenzie Given this question in particular, it's a bold assumption. – sweenish Nov 18 '19 at 15:06
  • @Aconcagua Yes, I have. It doesn't change my opinion on how to go about recommending vectors. – sweenish Nov 18 '19 at 15:07
  • 1
    @sweenish It is pretty common on SO to give additional advice in comments while not wanting (or being able) to write a full answer. We do not know the concrete scenario this question was asked for, especially we do not know if the question author is *forced* to use an array or if she/he might fall back to *better* alternatives. In the latter case, the vector advise *is* useful. And if none of the answers below would have mentioned it, the advice would be lost (be aware that the comment was posted before any of the answers). – Aconcagua Nov 18 '19 at 15:16
  • @Aconcagua And as I said, I disagree. All the "this is justified" reasoning relies on heavy assumptions that I simply disagree with. I don't see a need to take this further. – sweenish Nov 18 '19 at 15:51
  • @Aconcagua It's also common to give answers in comments. You only get in trouble when the OP is speaking a foreign language, though. If we're going to use "it's common" as a justification, there's no room for a rebuttal. Might as well have said, "It's whatever." – sweenish Nov 18 '19 at 15:53

3 Answers3

7

You have to reallocate memory for the array of a greater size. Otherwise the program will have undefined behavior.

For example

int SIZE = 10;
int *p = new int[SIZE];
for(int i = 0; i < SIZE; ++i)
  p[i] = i;

int *tmp = new int[SIZE + 3];

std::copy( p, p + SIZE, tmp );
delete []p;
p = tmp;

p[SIZE++] = 10;
p[SIZE++] = 11;
p[SIZE++] = 12;

Or instead of the last three statements you can write

for ( const int &value : { 10, 11, 12 } ) p[SIZE++] = value;

Of course in such cases it is better to use the standard container std::vector.

In fact the code above is similar to the following

#include <vector>

//...

std::vector<int> v( 10 );

for ( int i = 0; i < v.size(); i++ ) v[i] = i;

v.reserve( 13 );
for ( const int &value : { 10, 11, 12 } ) v.push_back( value );

except that all the memory management is done internally by the vector.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 1
    Is it wrong to shake in disgust when looking at `p[SIZE++]`? – nada Nov 18 '19 at 14:23
  • As we are deleting the old array anyway, I'd prefer [`std::move`](https://en.cppreference.com/w/cpp/algorithm/move) over `std::copy` – while irrelevant for integers, it might make quite a difference for complex types (like `std::string`)... – Aconcagua Nov 18 '19 at 14:47
  • @Aconcagua I agree with you. – Vlad from Moscow Nov 18 '19 at 14:48
  • Hm, not necessarily equivalent, the constructor might decide to reserve more elements right from the start, in which case re-allocation might not occur. And `std::vector` *would* move, if possible... – Aconcagua Nov 18 '19 at 14:58
3

The second option is the correct way. The first option won't always complain, but you are writing to memory that has not been set aside for your array; it has been set aside for something else, and you don't know what. Sometimes it will behave okay, sometimes it won't. Assigning to an array outside its range is Undefined Behavior, and we should avoid it.

sweenish
  • 4,793
  • 3
  • 12
  • 23
3

In your first example suggestion:

p[10] = 10;
p[11] = 11;
p[12] = 12;

You will be overwriting memory that you don't own, which can lead to a crash. You need to reallocate your original array.

const int oldSize = SIZE;
SIZE = 13;
int *newP = new int[SIZE];
memcpy(newP, p, oldSize * sizeof(int));
for (int i = oldSize; i < SIZE; ++i)
{
    newP[i] = i;
}

delete[] p;
p = newP;

Your second example would work, but is slightly less efficient, because you're re-calculating the values with each reallocation. In my example above, you only re-calculate the new values.

Alternatively, you should look at std::vector which is designed specifically for this purpose (a dynamically sizing array).

std::vector<int> p;
for (int i = 0; i < 10; ++i)
{
    p.push_back(i);
}

Here the std::vector manages the allocation internally, so you don't have to worry about new and delete.

Mark Ingram
  • 71,849
  • 51
  • 176
  • 230
  • 4
    Side note: `memcpy` usually is invalid if complex objects are involved (like `std::string`). For consistency, I'd then avoid `memcpy` even for types where it actually is allowed in favour of the C++ means like `std::copy`. – Aconcagua Nov 18 '19 at 14:30
  • Yep I agree, the original intention of my answer was to preserve the "style" of the question (i.e. raw pointers and manual memory management), but yes, the memcpy should be discouraged. – Mark Ingram Nov 18 '19 at 14:36