Reputation: 75
I am trying to implement Vector::resize()
function in C++. I think I handled each situation but still get a bad_alloc
error. Three cases in this resize implementation:
new_size
is smaller than the old_size
(in my code, size
);new_size
is bigger than size
but smaller than capacity;new_size
is bigger than capacityHere is my code:
void Vector::resize(int new_size)
{
//if the new_size is smaller, make the size smaller, don't need to worry about memory
//the content is reduced to its first n elements
//remove those beyond and destroy them
if(new_size < size){
for(int i = size-1; i > new_size; i--){
erase(i);
}
size = new_size;
}
//if the new_size is bigger
//case 1: new_size is smaller than capacity
//inserting at the end of as many elements as needed
if(new_size > size && new_size < capacity){
for(int i=size; i < new_size; i++){
insert(i, 0.0);
}
size = new_size;
}
//case 2: new_size is greater than capacity
//increase the capacity of the container
//increase the capacity to new_size
double *tmp_data = new double(new_size);
//transfer data to tmp_data
for(int i=0; i < size; i++)
{
tmp_data[i] = data[i];
}
data = tmp_data;
delete [] data;
size = new_size;
capacity = new_size;
}
Upvotes: 0
Views: 979
Reputation: 20771
As pointed out by Barry, you had a few bugs in the original.
Here is your code with a few suggestions:
void Vector::resize(int new_size)
{
if(new_size <= size) { // use "<=" here
// if you are dealing with doubles, what is there to erase?
// (I would remove that loop)
for(int i = size-1; i > new_size; i--){
erase(i);
}
size = new_size;
return; // you're done here, you can return
}
if(new_size <= capacity) { // again "<=", if you return, then no need for anything more
// "insert()" sounds confusing, you're doing a set() here
for(int i=size; i < new_size; i++){
insert(i, 0.0);
}
size = new_size;
return; // again, you can now return, you're done
}
double *tmp_data = new double(new_size);
// you could use std::copy() here
for(int i=0; i < size; i++)
{
tmp_data[i] = data[i];
}
// as indicated by Barry, you could inverse these
delete [] data;
data = tmp_data;
size = new_size;
capacity = new_size;
}
I removed all your comments and put my own for you perusal.
Another way to handle 3 cases like these is to use the else keyword like so:
if(new_size <= size) {
...
} else if(new_size <= capacity) {
...
} else {
...
}
And to make it clear, you could have three sub-functions you call from each ...
cases. That way you see the main logic of your resize()
function.
Upvotes: 0
Reputation: 303347
There are several things wrong with this code. The one that jumps out first is:
//increase the capacity to new_size
double *tmp_data = new double(new_size);
You intend to allocate an array, but are actually allocating a single double
. You meant:
double *tmp_data = new double[new_size];
Although, once you fix that...
data = tmp_data;
delete [] data;
You want to do those in the opposite order, otherwise you're leaving yourself with a deleted member.
And once you fix that, you want to return
from your cases early. You have three cases (not two, as your comments would suggest), and you only want to reallocate in the case that you actually need to (i.e. case #3). As-is, you're reallocating in all your cases.
Upvotes: 5