Reputation: 191
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
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
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
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:
E.g.:
std::vector<int>
std::array<int, 10>
Example:
for(int i=1; i<10; i++)
{
auto foo = std::unique_ptr<int[]>(new int [i]);
/*
...
*/
};
new[]
is matched by a call to delete[]
Upvotes: 2
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
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
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