peugas
peugas

Reputation: 191

Dynamic memory allocation in a cicle - c++

What's the best way to dynamically allocate memory in a loop?

1.Free the memory every loop?

int *foo;
for(int i=1;i<10;i++)
{
    foo = new int [i];
    /*
    ...
    */
    delete foo;
 }

or

2.Free the memory in the end?

int *foo;
for(int i=1;i<10;i++)
{
    foo = new int [i];
    /*
    ...
    */
 }
 delete foo;

Upvotes: 1

Views: 1149

Answers (6)

DFalgout
DFalgout

Reputation: 1

It is best to avoid what you are currently trying to do, use a vector. However, if this is purely for a learning exercise, I would recommend storing each pointer (new int[]) in an array. The reason for this, if it is not clear at this point, is because you keep assigning a new pointed at array in memory, then lose the reference of it by assigning new memory to the same pointer without calling delete[].

With a bit better design, you could, as I mentioned prior, is to store an array of such pointers e.g. *foo -- then you can clean up memory in the destructor ~Foo(). Just an idea.

Upvotes: 0

James Kanze
James Kanze

Reputation: 153929

First, there is no good solution using new, period. The argument would be a new std::vector each time in the loop, versus one outside of the loop, with a resize each time through the loop:

std::vector<int> foo;
for ( int i = 1; i < 10; ++ i ) {
    foo.resize( i );
    //  ...
}

vs.

for ( int i = 1; i < 10; ++ i ) {
    std::vector<int> foo( i );
    //  ...
}

If you're doing any real work in the loop, the difference is likely not to be significant, however...

You can improve the first version by using reserve:

std::vector<int> foo;
foo.reserve( 10 );
for ( int i = 1; i < 10; ++ i ) {
    foo.resize( i );
    //  ...
}

If the rest of the loop is pretty trivial, this could be faster. For that matter, if the maximum size is known and isn't too big, you can use:

int foo[10];
for ( int i = 1; i < 10; ++ i ) {
    //  ...
}

In a lot of cases, this is perfectly acceptable, and it will be the fastest (although again, most of the time, the performance difference will be negligible, and you'll loose the advantages of std::vector—which in most cases, includes bounds checking when optimization isn't active).

Upvotes: 1

quantdev
quantdev

Reputation: 23803

  • In your first example, you have undefined behavior, you need to use delete[] to delete an array allocated by new []

  • In your second example, same issue, but even if you fix it you will have a memory leak, since only the last allocated array will be deleted.


Solution:

  • The best way is to use a standard container :

E.g.:

std::vector<int>
std::array<int, 10>
  • Or you can still use a smart pointer :

Example:

for(int i=1; i<10; i++)
{
    auto foo = std::unique_ptr<int[]>(new int [i]);
    /*
    ...
    */
 }; 
  • Or, if you really cant, then make sure that each call to new[] is matched by a call to delete[]

Upvotes: 2

bfair
bfair

Reputation: 1111

The first example is better, though you should call:

delete [] foo;

To free the entire block.

Your second example is a memory leak. Here's why:

During the first iteration, memory is allocated and foo is set to point to the start of the allocated buffer. Every iteration after the first, the memory which was allocated in the previous iteration is not being freed. Instead, foo is just being set to point to a newly allocated buffer. After that, there is no longer any way to reference the previously allocated buffer.

Upvotes: 1

eferion
eferion

Reputation: 902

Option 1: Multiple allocation / deallocation = bad performance

for(int i=1;i<10;i++)
{
    foo = new int [i];
    /*
    ...
    */
    delete[] foo;
}

Option 2: Multiple allocations / one deallocation = memory leak

int *foo;
for(int i=1;i<10;i++)
{
    foo = new int [i];
    /*
    ...
    */
}
delete[] foo;

Option 3: One allocation / one deallocation = OK if you need dynamic memory

int *foo = new int [10];
for(int i=1;i<10;i++)
{
    /*
    ...
    */
}
delete[] foo;

Option 4: Avoid dynamic allocation / deallocation

for(int i=1;i<10;i++)
{
  int foo[ i ];
    /*
    ...
    */
}

Upvotes: 5

Some programmer dude
Some programmer dude

Reputation: 409196

First of all, when you use the new[] operator you need to match it with the delete[] operator, so you should do delete[] foo.

Secondly, if you do delete[] after the loop, you will only free the last memory you allocated, leading to memory leaks.

Thirdly, do you really need to use raw pointers? Can't you use e.g. std::vector instead?

Upvotes: 10

Related Questions