Пользовательский векторный класс C ++: поведение указателя - PullRequest
0 голосов
/ 18 марта 2020

Я пишу собственный векторный класс для курса. Мы должны реализовать функцию push_back, которая перераспределяет новую память, когда начальный массив заполнен. Моя реализация должна работать, однако при печати значений я всегда получаю «0» в качестве первого элемента, несмотря на указание на место в памяти, где хранится другое значение. Это не найти мою ошибку, или что здесь происходит. Другие значения работают.

Вот код:

#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
  }
 }
};

Теперь к основному:

#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;
}

Вывод:

0x560db3004ea0 1
/* message */
0x560db3004ea0 1
/* message */
0x560db3004ea0 0
0
2
3
4
5
6

I значит, как это возможно. Это то же самое место в памяти, почему 1 вызывается изнутри функции push_back, и 0 при вызове из основного, несмотря на то, что он находится в том же месте в памяти?

1 Ответ

2 голосов
/ 18 марта 2020

Похоже, ваша проблема заключается в том, что и temp, и this имеют указатель на один и тот же data после this->reset(temp.begin());, а затем temp выходит из области видимости, делая доступ к this->data неопределенному поведению.

Исправление заключается в вызове

temp->reset(nullptr);

до того, как temp выйдет из области видимости, чтобы деструктор не освободил data.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...