Проблема с освобождением памяти (шаблон темы) - PullRequest
0 голосов
/ 16 июня 2020

Set.h

#ifndef Set_h
#define Set_h

#include <iostream>
using namespace::std;

template <class T>
class Set {
    T* group;
    int size_group;
public:
    Set():group(NULL),size_group(0){};
    Set(T*,int);
    Set(const Set<T>&);
    ~Set();


    bool isThere(const T&)const;
    void getType()const;

    Set<T>& operator =(const Set<T>&);
    bool operator ==(const Set<T>&) const;
    void operator +=(const T);
    void operator -=(const T&);
    Set<T>& operator +(Set<T>&);
    Set<T>& operator -(const Set<T>&);
    bool operator >(const Set<T>&)const;
    friend ostream& operator <<(ostream&,const Set<T>&);

};

//Realizations

template <class T>
Set<T>::Set(T* gro,int size):group(gro),size_group(size){}

template <class T>
Set<T>::Set(const Set<T>& obj){ // c'Ctor (copy)
    this->size_group = obj.size_group;
    this->group = new T[this->size_group];
    for (int i = 0; i < size_group; i++) {
        group[i] = obj.group[i];
    }
}

template <class T>
void Set<T>::getType() const{
    cout << "The type is: " << typeid(group).name() << endl;
}

template <class T>
Set<T>& Set<T>::operator = (const Set<T>& obj){
    this->size_group = obj.size_group;
    this->group = new T[size_group];
    for (int i = 0; i < size_group; i++) {
        this->group[i] = obj.group[i];
    }
    return *this;
}

template <class T>
bool Set<T>::operator==(const Set<T>& obj) const{
    int count = 0;
    T temp;
    if(this->size_group != obj.size_group)
        return false;
    for (int i = 0; this->size_group; i++) {
        temp = this->group[i];
        count = 0;
        for (int j = 0; j < obj.size_group; j++) {
            if(temp == obj.group[j])
                count++;
        }
        if(count != 1)
            return false;
    }
    return true;
}

template <class T>
void Set<T>::operator+=(const T var){
    if(!isThere(var)){
        T* Temp = new T[this->size_group+1];
        for (int i = 0; i < this->size_group; i++)
            Temp[i] = this->group[i];
        Temp[size_group] = var;
        delete [] this->group;
        this->size_group++;
        this->group = Temp;
    }

}

template <class T>
Set<T>& Set<T>::operator+(Set<T>& obj){ //
    if(obj.size_group > this->size_group){
        for (int i = 0; i < obj.size_group; i++){
            for (int j = 0 ; j < this->size_group; j++){
                if(!this->isThere(obj.group[i]))
                    *this += obj.group[i];
            }
        }
        return *this;
    }else{
        for (int i = 0; i < this->size_group; i++){
            for (int j = 0 ; j < obj.size_group; j++){
                if(!obj.isThere(this->group[i]))
                    obj += this->group[i];
            }
        }
        return obj;
    }
}


template <class T>
bool Set<T>::isThere(const T& var) const{
    for (int i = 0; i < this->size_group; i++) {
        if(this->group[i] == var)
            return true;
    }
    return false;
}




template <class T>
Set<T>::~Set() {
    delete [] group;
}

#endif /* Set_h */

Main:

#include "Set.h"

int main() {
    int arr[] = {3,7,8,1};
    int arr2[] = {1,2,5};

    Set<int> j(arr,4),l(arr2,3),k;

    k = j + l;
}

Я пытаюсь объединить два массива, но моя проблема связана с методом void Set<T>::operator+=(const T var) и этой строкой delete [] this-> group;

Я получаю эту ошибку:

Template & Exception (8421,0x1000dadc0) malloc: *** error for object 0x7ffeefbff400: pointer being Friday was not allocated
Template & Exception (8421,0x1000dadc0) malloc: *** set a breakpoint in malloc_error_break to debug

1 Ответ

0 голосов
/ 17 июня 2020

Ваш конструктор Set(T*,int) не выделяет память new[] для group, на которую указывает, что означает, что operator+=~Set(), и operator=) потерпят неудачу во время выполнения, когда они попытаются delete[] память, на которую указывает group, которая в вашем примере является локальной стековой памятью, которая принадлежит main() и передает ее объектам j и l.

Ваш конструктор Set(T*,int) должен new[] массив group и скопируйте в него содержимое массива input gro, аналогично тому, как это делает ваш конструктор копирования, например:

template <class T>
Set<T>::Set(T* gro, int size) : group(NULL), size_group(0)
{
    size_group = size;
    group = new T[size];
    for (int i = 0; i < size; i++) {
        group[i] = gro[i];
    }
}

Кстати, ваше operator= вызывает утечку памяти, так как не delete[] текущий массив group перед назначением нового массива group. Он должен создавать временный массив, аналогично тому, как это делает ваш operator+=, например:

template <class T>
Set<T>& Set<T>::operator=(const Set<T>& obj)
{
    if (this != &obj){
        T* Temp = new T[obj.size_group];
        for (int i = 0; i < obj.size_group; i++)
            Temp[i] = obj.group[i];
        delete [] group;
        group = Temp;
        size_group = obj.size_group;
    }
    return *this;
}

Или лучше, используйте вместо этого свой конструктор копирования через идиому копирования-подкачки :

template <class T>
Set<T>& Set<T>::operator=(const Set<T>& obj)
{
    if (this != &obj){
        Set<T> temp(obj);
        std::swap(group, temp.group);
        std::swap(size_group, temp.size_group);
    }
    return *this;
}

Кроме того, ваш operator+ реализован неправильно. Ему нужно вернуть новый Set, который является объединением массивов *this и obj, а не изменять obj или *this вообще. Таким образом, вместо этого он должен выглядеть примерно так:

template <class T>
Set<T> Set<T>::operator+(const Set<T>& obj) const
{
    Set<T> res(*this);
    for (int i = 0; i < obj.size_group; i++) {
        res += obj.group[i];
    }
    return res;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...