Работает ли delete [] с универсальными массивами?Если так, то почему использование std :: vector :: erase вызывает ошибку при освобождении памяти - PullRequest
5 голосов
/ 07 мая 2019

Я пытался работать с круглыми массивами, и в итоге я написал класс CircularArray, для которого я прикрепил код.Он использует общий указатель для массива.Когда я пытаюсь создать список таких круговых массивов, используя std :: vector, я сталкиваюсь с проблемой, когда пытаюсь использовать стирание для него.

Я не понимаю, почему это так, так как я думаю, чтодеструкторы и конструктор копирования работают достаточно хорошо.

Может кто-нибудь помочь с этим?

Код:CircularArray Class

template<class T> class CircularArray
    {
        //Class denoted by 'T' is expected to have a functional assignment operator, i.e. operator=(const T& ext) {} in place
    protected:
        int size=0;
        int ori=0;
        T* array;
    private:
        int pos=0;

    public:
        CircularArray() : CircularArray(0) {}
        CircularArray(int s) {size=s;array=new T[s];}
        CircularArray(T* ptr,int s)// : CircularArray(s)
        {
            size=s;array=new T[s];
            for(int i=0;i<size;i++)
                array[i]=ptr[i];
        }
        CircularArray(const CircularArray<T>& arr) : CircularArray(arr.size)
        {
            for(int i=0;i<size;i++)
                array[i]=arr.array[i];
        }
        ~CircularArray() {delete[] array;}
        ...

Тестовый код

int main()
{
    std::vector<CircularArray<int>> test;
    int *a1=new int[3] {1,2,3},*a2=new int[3] {1,2,3},*a3=new int[3] {1,2,3};
    CircularArray<int> n1(a1,3),n2(a2,3),n3(a3,3);
    test.push_back(n1);
    test.push_back(n2);
    test.push_back(n3);
    test.erase(test.begin()+1);
    for(auto v : test)
    {
        for(int i=0;i<3;i++)
            cout << v[i];
        cout << "\n";
    }
}

Эта программа выдает неверный вывод после обнаружения удаленной части вектора.Вэлгринд говорит, что при попытке чтения свободной памяти происходит повреждение памятиЧто не так?

Ответы [ 2 ]

8 голосов
/ 07 мая 2019

Векторные элементы должны быть назначаемыми для копирования / перемещения, однако вы полагаетесь на оператор назначения копирования по умолчанию, который не создает никакой новой памяти. Все ваши назначенные объекты совместно используют одно и то же пространство памяти, что впоследствии приводит к двойному освобождению.

Ваши конструкторы хороши, но вам также понадобится оператор копирования / перемещения.

Читайте о правиле пяти .

Также рассмотрите возможность использования std::vector для резервного копирования хранилища; это будет намного проще.

6 голосов
/ 07 мая 2019

Работает ли delete [] с универсальными массивами?

Да.

Ваш (неявно сгенерированный) оператор копирования и перемещения назначен неправильно.Они будут копировать указатель члена.Затем у вас есть два указателя на один и тот же массив, и один деструктор удаляет его один раз, а другой удаляет его второй раз, что приводит к неопределенному поведению.

При ручном управлении динамическим ресурсом важно отслеживатьи убедитесь, что он выпущен ровно один раз.Типичным решением является использование умного указателя.Ваш класс обладает уникальным владением (или если бы он случайно не поделился владением в операторах присваивания) динамического массива, поэтому подходящий указатель был бы подходящим выбором.

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

...