Нежелательные значения в первых двух элементах класса массива с изменяемым размером с перегрузкой оператора скобок

Я работаю над проектом для школы, где мы создаем класс ExpandArray, который будет динамически выделять массив, и по мере добавления или удаления значений он будет расширяться или сжиматься в зависимости от процента.

Проблема, с которой я сталкиваюсь, связана с функцией перегрузки оператора скобок. У меня версия работает корректно. В моей основной я создаю объект с именем ea типа ExpandArray и отправляю ему массив значений от 1 до 10. Затем я cout ‹‹ ea(3,7); который должен вывести 4, 5, 6, 7, 8.

Это работает в одной версии, которую я скомпилировал и которую использовал для тестирования, но в любой другой версии, даже когда я создаю новый проект с нуля, копирую и вставляю текст из рабочей версии, я получаю нежелательное значение, нежелательное значение, 6, 7, 8.

Я даже проверил путь к заголовочному файлу, чтобы убедиться, что тестовая версия случайно не создавалась на основе файлов в другом месте.

Ниже приведен соответствующий код, который у меня есть:

template<class OT>
ostream& operator<<(ostream& os, const ExpandArray<OT>& ea)
{
    if(ea._size == 0)
        os << "This array is empty";
    else
    {
        os << ea._array[0];
        for(unsigned i = 1; i < ea._size;++i)
            os << ", " << ea._array[i];
    }
    return os;
}

template<class T>
ExpandArray<T> ExpandArray<T>::operator()(int first, int last)const
{
    int Afirst = first - _Vindex;
    int Alast = last - _Vindex;
    if(Afirst < 0 || Afirst > _size - 1 || Alast < 0 || Alast > _size - 1)
    {
        cout << "Error: ExpandArray<T>::operator()(int first, int last)const" << endl;
        cin.get();
        return *this;
    }
    ExpandArray<T> temp(_Vindex, _perc);
    for(unsigned i = Afirst;i <= Alast;++i)
    {
        temp.append(_array[i]);
    }
    return temp;
}

template<class T>
void ExpandArray<T>::append(const T& t)
{
    if(_size >= _alloc)
    {
        if(_alloc < MIN_ALLOC)
        {
            _alloc = MIN_ALLOC;
            _array = new T[_alloc];
        }
        else if(_size <= (_alloc / (_perc + 1)))
        {
            _alloc /= (_perc + 1);
            T* temp;
            temp = new T[_alloc];
            for(unsigned i = 0;i < _size; ++i)
                temp[i] = _array[i];
            _array = temp;
            delete &temp;
        }
        else
        {
            _alloc *= (_perc + 1);
            T* temp;
            temp = new T[_alloc];
            for(unsigned i = 0;i < _size; ++i)
                temp[i] = _array[i];
            _array = temp;
            delete &temp;
        }
    }
    _array[_size++] = t;
}

И мой главный:

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

int main()
{
    int arr[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
    ExpandArray<int> ea(arr, 10);
    cout << ea(3,7) << endl;

    return 0;
}

Если я распечатаю _array[3] в качестве последней строки функции перегрузки оператора скобок, она выведет правильное значение 4. Если я распечатаю тот же _array[3] в качестве первой строки в функции перегрузки оператора вставки, я получить ненужную стоимость. Первые два распечатываемых элемента представляют собой разные случайные огромные числа каждый раз, когда я их создаю и запускаю. Для справки, при его запуске теперь отображаются 6035096, 6033256, 6, 7, 8.

Любая помощь будет оценена по достоинству. Спасибо.


person Andrew Portlock    schedule 24.04.2018    source источник
comment
delete &temp; неверно, здесь нет необходимости брать адрес, нет необходимости удалять новые элементы, пропуская старые элементы, оставляя вас с оборванным указателем. Все эти вещи приводят к неопределенному поведению. Должно быть std::swap(_array, temp); delete [] temp;   -  person user7860670    schedule 25.04.2018
comment
Спасибо, однако это все еще печатает ненужные значения для первых двух элементов.   -  person Andrew Portlock    schedule 25.04.2018
comment
У вас есть конструктор копирования?   -  person scohe001    schedule 25.04.2018
comment
Да, это просто делает всех участников = ea.member   -  person Andrew Portlock    schedule 25.04.2018
comment
Ну, это ваша проблема. Возвращаемый вами ExpandArray является копией temp, поэтому он просто скопирует указатель _array из temp. Но тогда temp выходит за рамки и освобождает эту память! Вы остались с неопределенным поведением. Вам нужно создать глубокую копию вместо поверхностной. Создайте и разместите новый _array в конструкторе копирования.   -  person scohe001    schedule 25.04.2018
comment
Вы пробовали использовать дезинфицирующее средство для адресов valgrind или clang/gcc? Бесполезные ценности заставляют меня думать, что это пожизненная проблема, и любой из этих инструментов поможет.   -  person Stephen Newell    schedule 25.04.2018
comment
Удивительно, спасибо! Я понятия не имею, почему это работает в той версии, которая у меня есть без этого метода, но теперь он также работает в этой версии.   -  person Andrew Portlock    schedule 25.04.2018


Ответы (1)


Спасибо scohe001!!!

Мой конструктор копирования был следующим:

template<class T>
ExpandArray<T>::ExpandArray(const ExpandArray& ea)
{
    _array = ea._array;
    _size = ea._size;
    _alloc = ea._alloc;
    _Vindex = ea._Vindex;
    _perc = ea._perc;
}

Я изменил его на:

template<class T>
ExpandArray<T>::ExpandArray(const ExpandArray& ea)
{
    _array = new T[ea._size];
    for(unsigned i = 0;i < ea._size;++i)
    {
        _array[i] = ea._array[i];
    }
    _size = ea._size;
    _alloc = ea._alloc;
    _Vindex = ea._Vindex;
    _perc = ea._perc;
}
person Andrew Portlock    schedule 24.04.2018
comment
Рад, что смог помочь! Несколько простых советов: я не уверен, что делают все ваши участники, но если _alloc — это то, сколько места выделено, вам не следует делать _alloc = ea._alloc, потому что вы выделили ea._size места, верно? Для конструктора копирования я бы предложил настроить элементы, такие как конструктор по умолчанию (вероятно, установить все на 0), а затем пройтись по ea и вызвать append. Лучше использовать то, что вы уже создали, так будет меньше ошибок! - person scohe001; 25.04.2018