I was making a std::vector
like clone for a fun little project in C , and I've come across the following problem: I'm trying to implement the method pop_back
but for some reason, I can't get it to work. The class I'm using is called Array
and is defined in ../d_arrays/d_array.h
and ../d_arrays/d_array.cpp
I have a main.cpp
file in the root folder. Here is what I have so far:
RootDir/d_arrays/d_array.h
#include <iostream>
using namespace std;
class Array {
public:
Array(int len);
void pop_back();
void print();
private:
int* _array = NULL;
int _len = 0;
};
RootDir/d_arrays/d_array.cpp
#include <iostream>
#include "d_array.h"
using namespace std;
Array::Array(int len) {
_array = new int[len];
_len = len;
}
void Array::pop_back() {
_len--; // reduce length by 1
int* tmp = new int[_len]; // create temp copy
for (int i = 0; i < _len; i ) {
tmp[i] = _array[i];
}
_array = tmp;
delete[] tmp;
}
void Array::print() {
for (int i = 0; i < _len; i ) {
cout << _array[i] << " ";
}
cout << endl;
}
RootDir/main.cpp
#include <iostream>
#include "d_arrays/d_array.h"
using namespace std;
int main() {
Array a = Array(10);
cout << "Before: ";
a.print();
a.pop_back();
cout << "After: ";
a.print();
return 0;
}
Im using g -o main main.cpp d_arrays/d_array.cpp
to compile my code and ./main
to run it.
whenever I run ./main
I get the following output:
Before: 0 0 0 0 0 0 0 0 0 0
After: 0 0 118968336 21854 0 0 0 0 0
What is happening here?
CodePudding user response:
Your problem is here:
delete[] tmp;
Now:
_array = tmp
means:
Point _array to the memory address that tmp is pointing to.
Now, _array is pointing to &tmp (& means 'address of'), and then you delete tmp, which causes issues.
Also resizing the entire array would be ok if the array is small. But it would not be ok if the array is big. For example, if the array contains millions of elements, resizing the array is going to take a long time. So you can just not resize the array, as _len is what handles the number of elements.
So the new pop_back function can be as follows:
void Array::pop_back()
{
_len--; // reduce length by 1
/* int* tmp = new int[_len]; // create temp copy
for (int i = 0; i < _len; i )
{
tmp[i] = _array[i];
}
_array = tmp;
delete[] tmp; */
}
As you can see I've commented out all code except _len--;
But if you really want to resize the array at some point, you can declare a separate function for that as such:
void Array::shrink_to_fit()
{
int* tmp = new int[_len]; // create temp copy
for (int i = 0; i < _len; i )
{
tmp[i] = _array[i];
}
delete[] _array; // Delete what _array is pointing to
_array = tmp; // Point _array to the memory address that tmp is pointing to
}
But with this new function, don't forget to define shrink_to_fit() in your class definition. So the new class definition:
class Array
{
public:
Array(int len);
void pop_back();
void print();
void shrink_to_fit();
private:
int* _array = NULL;
int _len = 0;
};