Reputation: 175
I am writing a custom vector class for a course. We are supposed to implement a push_back function that reallocates new memory when the initial array is full. My implementation should work, however when printing the values I always get a "0" as first element, despite pointing to a place in memory where another value is stored. It do not find my mistake, or what is going on here. The other values work.
Here is the code:
#include <initializer_list>
#include <stdexcept>
#include <algorithm>
#include <iostream>
using std::size_t;
class Vector{
double* data; //array to store the data
size_t sz; //count number of elements in the vector
size_t max_sz; //max elements
public:
// constructor default max_sz is set to 5
Vector(size_t n): sz{0}, max_sz{n < 5? 5: n}, data{new double[n]}{}
double* begin() { return this->data; } // return a pointer to the first element
Vector(std::initializer_list<double> data): Vector(data.size()){
for(const auto &elem: data){
this->data[sz++] = elem;
}
}
~Vector(){ delete[] this->data; } //destructor
size_t size() const { return this->sz; }
size_t capacity() const { return max_sz; };
double* at(size_t position) { return this->begin() + position; } //convenience function
void reset(double* new_data) {this->data = new_data; } //reset pointer to new array
void push_back(double value){
//test if array is "full"
if (this->size() == this->capacity()) {
// create a new temp array, copy the values reset the pointer and delete
Vector temp(this->capacity() * 2);
//copy elements from this->data to temp
for (size_t i = 0; i < this->size(); i++) {
*(temp.at(i)) = *(this->at(i));
}
*(temp.at(this->size())) = value; //"push_back" the value
//control statements
std::cout << temp.begin() << " " << *(temp.begin()) << '\n';
std::cout << "/* message */" << '\n';
this->reset(temp.begin()); //reset the pointer from this->data to temp
//more control statements
std::cout << this->begin() << " " << *(this->begin()) <<'\n';
std::cout << "/* message */" << '\n';
this->sz++; // increase size
this->max_sz = temp.capacity(); // update capacity
} else {
// stuff to follow
}
}
};
Now to main:
#include "vector.h"
int main(int argc, char const *argv[]) {
Vector a{1,2,3,4,5}; //usie initializer list
a.push_back(6); //call push_back
//control statements, the same will be call from within push_back
//this is the core problem, because a.begin() references to the same memory as this->begin()
//from within a.push_back(), but the values are different.
//How can the same memory block save two different values?
std::cout << a.begin() << " " << *(a.begin()) << '\n';
//to show that the rest actually works:
for (size_t i = 0; i < a.size(); i++) {
std::cout << *(a.begin()+i) << '\n';
}
return 0;
}
Output:
0x560db3004ea0 1
/* message */
0x560db3004ea0 1
/* message */
0x560db3004ea0 0
0
2
3
4
5
6
I mean, how is this possible. It's the same place in memory, why is there a 1 when called from inside the push_back function, and a "0" when call from main, despite poiting to the same place in memory?
Upvotes: 0
Views: 257
Reputation: 10857
Your problem appears that both temp
and this
own the pointer to the same data
after this->reset(temp.begin());
and then temp
goes out of scope making access to this->data
undefined behavior.
The fix is to call
temp->reset(nullptr);
before temp goes out of scope so that the destructor does not free the data
.
Upvotes: 2