Explain the reason for the baga in my code when dealing with the links and indicators.



  • My friend recently sent me a piece of his code, and we're being asked by the lab to write our collections, so it's about a hand-to-hand memory work. Actually, there's a piece of his headline file with the collection.

    #pragma once
    

    #include <vector>

    struct Point {
    double x, y;
    Point() { x = 0; y = 0; }
    };

    namespace Data {
    template<typename T>
    class Array {
    private:
    T *arrayPtr; // Указатель на массив
    unsigned int count; // Размер массива
    public:
    Array<T>(); // Конструктор
    Array<T>(int); // Объявление и инициализация
    Array<T>(const Array<T>&); // Конструктор копирования
    void Add(T); // Добавить в конец
    void Clear(); // Очистить
    void Allocate(int); // Изменить размер
    ~Array() { delete[] arrayPtr; } // Деструктор
    unsigned int size() const { return count; } // Количество элементов
    // Операторы
    Array& operator=(const Array&); // Присваивание
    T& operator[] (unsigned int) const; // Индексация
    T& operator[] (int) const; // Индексация
    };

    // Копирующий конструктор
    template<typename T>
    Array<T>::Array(const Array<T>& arr) {
    count = arr.count;
    Allocate(count);
    //arrayPtr = new T[count];
    for(int i = 0; i < count; i++) {
    this->arrayPtr[i] = arr.arrayPtr[i];
    }
    }

    template<typename T>
    Array<T>&
    Array<T>::operator=(const Array<T>& arr) {
    if(this != &arr) { // Чтобы избежать присваивания самому себе
    this->count = arr.count;
    Allocate(count);
    //if (this->arrayPtr != arr.arrayPtr) { // Если новый массив - не модифицированный старый
    // if (arrayPtr) { delete[] arrayPtr; } // Удаляем указатель на старый
    //}
    //arrayPtr = new T[this->count];
    for (unsigned int i = 0; i < this->count; i++) {
    this->arrayPtr[i] = arr.arrayPtr[i];
    }
    }
    return *this;
    }

    template<typename T>
    T& Array<T>::operator[](unsigned int i) const {
    // Если вышли за пределы массива - выдаём exception
    return (i < this->count) ? arrayPtr[i] : throw std::out_of_range("Array index out of range");
    }

    template<typename T>
    T& Array<T>::operator[](int i) const {
    // Если вышли за пределы массива - выдаём exception
    return ((i < this->count) && (i >= 0)) ? arrayPtr[i] : throw std::out_of_range("Array index out of range");
    }

    template<typename T>
    Array<T>::Array() {
    this->count = 0;
    arrayPtr = new T[count];
    }

    template <typename T>
    Array<T>::Array(int size) {
    this->count = size;
    arrayPtr = new T[this->count];
    for (int i = 0; i < this->count; i++)
    {
    arrayPtr[i] = T;
    }
    }

    // Изменение размера
    template <typename T>
    void Array<T>::Allocate(int newSize) {
    T *temp = new T[newSize]; // Создаём новый массив
    for (int i = 0; i < newSize; i++) {
    if (i < this->count) { // Пока есть элементы - копируем в новый массив
    temp[i] = this->arrayPtr[i];
    }
    else { // Начались новые элементы
    temp[i] = T(); // Заполняем пустыми
    }
    }
    delete[] this->arrayPtr; // Удаляем старый массив
    this->arrayPtr = temp; // Сохраняем новый
    this->count = newSize; // Сохраняем размер
    }

    // Добавление элемента в конец
    template <typename T>
    void Array<T>::Add(T value) {
    unsigned int temp = this->count + 1; // Сохранили значение увеличенного на 1 массива
    Allocate(temp); // Увеличили массив на 1
    this->count = temp; // Сохранили размер массива
    this->arrayPtr[this->count - 1] = value; // Запомнили добавленный элемент
    }

    // Очистка
    template <typename T>
    void Array<T>::Clear() {
    this->count = 0;
    Allocate(this->count);
    }

    Array<Point> SortPoints(Array<Point> vectorPoints);
    Array<Point> GeneratePoints(int);
    //std::vector<Point> SortPoints(std::vector<Point> vectorPoints);
    }

    And here's the code he tested her.

    #include <iostream>
    #include "data.h"
    using namespace std;

    int main(int argc, char** argv)
    {
    Point point;
    point.x = 5;
    point.y = 3;
    Data::Array<Point> userPoints;
    userPoints.Add(point);
    point.x = 7;
    point.y = 9;
    userPoints.Add(point);
    cout << userPoints[0].x << " " << userPoints[0].y<<"\n";
    cout << userPoints[1].x << " " << userPoints[1].y << "\n";
    Point dump = userPoints[0];
    userPoints[0] = userPoints[1];
    userPoints[1] = dump;
    cout << userPoints[0].x << " " << userPoints[0].y << "\n";
    cout << userPoints[1].x << " " << userPoints[1].y << "\n";
    system("pause");
    return 0;
    }

    I understand that a constant increase in the size of the unit is a terrible move, it's easier to keep a separate amount of memory and a number of elements so that the size of the body can be increased at times. It's not that. It's about what this code gives to the console.

    5 3
    7 9
    5 3
    7 9

    Personally, I couldn't find a reason for such results, but I'm definitely missing something, maybe one of you could explain it?

    P.S. Please don't point out the solution, ask the cause of the problem, not how to fix it?



  • I'll risk assuming there's a problem with the thermal operator. The terminal operator returns r-value, and the reference returned from the method refers specifically to the temporal variable with the r-value rather than to the mass element.

    PS code:

    1. why accentuate count before or after call Allocateif Allocate It's the field. count new meaning?

    2. Indicator signatures are strange. Usually, in the collections, the constant overloading of the indexor returns the constant reference and the non-constant overloading is the usual reference. Because when someone writes const Data::Array<Point> - he's expecting a complete recurrence

    3. Allocate will lead to memory leaks if the code in the cycle leaves the exception

    4. In method Allocate Appropriation temp[i] = T() superfluous for all but primitive. new




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2