Ошибка деконстрактора объекта в pair

Программа работает отлично,но при завершении (return 0) и попытке деконстрактора сработать на объект класса в pair выдает ошибку:

HEAP[program.exe]: Invalid address specified to RtlValidateHeap( 0000021B54F40000, 0000021B54F50CA0 )

Вот полный код программы:

main.cpp

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


int main() {
    size_t temp = 0;

    IntSet intset1;
    IntSet intset2;



    intset1.pushBack(1);
    intset1.pushBack(2);
    intset1.pushBack(2);
    intset1.pushBack(5);
    intset1.pushBack(6);    // [1, 2, 5, 6]

    intset2.pushBack(6);
    intset2.pushBack(8);
    intset2.pushBack(2);
    intset2.pushBack(15);
    intset2.pushBack(27);   // [6, 8, 2, 15, 27]

    IntSet* intset3 = intset1.relative_complement(intset2); // [1, 2, 5, 6] / [6, 8, 2, 15, 27] = [1, 5]
    IntSet* intset4 = intset1.union_(intset2);  // [1, 2, 5, 6] + [6, 8, 2, 15, 27] = [1, 2, 5, 6, 8, 15, 27]

    pair<IntSet, IntSet> p = intset1.even_odd_division(intset2);


    temp = intset3->size();
    for (size_t i = 0; i < temp; i++) {
        cout << (*intset3)[i] << std::endl;
    }

    cout << "\n" << std::endl;

    temp = intset4->size();
    for (size_t i = 0; i < temp; i++) {
        cout << (*intset4)[i] << std::endl;
    }

    return 0;
}

IntSet.h

#ifndef INT_SET_H
#define INT_SET_H


class IntSet {
public:
    IntSet();
    ~IntSet();
public:
    size_t size() const;
public:
    void pushBack(const int value);
    void remove(size_t index);
    int search(int num);
    IntSet* union_(IntSet& object_1);
    IntSet* relative_complement(IntSet& object_1);
    std::pair<IntSet, IntSet> even_odd_division(IntSet& object_1);
public:
    int operator[](size_t index);
private:
    int* arr_;
    size_t size_{};
    size_t capacity_{};

    void addMemory();
};

#endif // !INT_SET_H

IntSet.cpp

#include <utility>
#include "IntSet.h"

void IntSet::pushBack(const int value) {
    if (search(value) == -1) {
        if (size_ >= capacity_) addMemory();
        arr_[size_++] = value;
    }
}

void IntSet::remove(size_t index) {
    for (size_t i = index + 1; i < size_; ++i) {
        arr_[i - 1] = arr_[i];
    }
    --size_;
}

int IntSet::search(int num) {
    for (size_t i = 0; i < size_; i++) {
        if (arr_[i] == num) {
            return (int)i;
        }
    }
    return -1;
}

IntSet* IntSet::union_(IntSet& object_1) {
    IntSet* NewIntSet = new IntSet;

    for (size_t i = 0; i < size(); i++)
    {
        NewIntSet->pushBack(arr_[i]);
    }
    for (size_t i = 0; i < object_1.size(); i++)
    {
        NewIntSet->pushBack(object_1.arr_[i]);
    }

    return NewIntSet;
}

IntSet* IntSet::relative_complement(IntSet& object_1) {
    IntSet* NewIntSet = new IntSet;
    int index = 0;

    for (size_t i = 0; i < size(); i++)
    {
        NewIntSet->pushBack(arr_[i]);
    }
    for (size_t i = 0; i < object_1.size(); i++)
    {
        index = NewIntSet->search(object_1.arr_[i]);
        if (index >= 0) NewIntSet->remove(index);
    }

    return NewIntSet;
}

void IntSet::addMemory() {
    capacity_ *= 2;
    int* tmp = arr_;
    arr_ = new int[capacity_];
    for (size_t i = 0; i < size_; ++i) arr_[i] = tmp[i];
    delete[] tmp;
}

int IntSet::operator[](size_t index) {
    return arr_[index];
}

size_t IntSet::size() const {
    return size_;
}

std::pair<IntSet, IntSet> IntSet::even_odd_division(IntSet& object_1) {
    IntSet EvenIntSet;
    IntSet OddIntSet;

    for (size_t i = 0; i < size(); i++) {
        if (arr_[i] % 2 == 0) EvenIntSet.pushBack(arr_[i]);
        else OddIntSet.pushBack(arr_[i]);
    }
    for (size_t i = 0; i < object_1.size(); i++) {
        if (object_1.arr_[i] % 2 == 0) EvenIntSet.pushBack(object_1.arr_[i]);
        else OddIntSet.pushBack(object_1.arr_[i]);
    }

    return std::make_pair(EvenIntSet, OddIntSet);;
}

IntSet::~IntSet() {
    delete arr_;
}

IntSet::IntSet() {
    arr_ = new int[1];
    capacity_ = 1;
}

Ответы (2 шт):

Автор решения: Everything

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

→ Ссылка
Автор решения: DmitryK

Как написал @Harry, у Вас проблема не в деструкторе, а в отсутствии конструктора копирования и оператора присваивания копированием в классе - т.е. правило трёх Вы не реализовали. правило трёх
Когда вы сами его не определяете, компилятор делает конструктор копирования по умолчанию, который просто делает копию полей. Т.е. просто копирует значение указателя на буфер, не копируя сам буфер.

std::pair<IntSet, IntSet> 
IntSet::even_odd_division(IntSet& object_1) 
{
    IntSet EvenIntSet;  // создали 2 локальных объекта, выделили память под массив
    IntSet OddIntSet;

    // заполнили их
    return std::make_pair(EvenIntSet, OddIntSet); // а теперь при создании пары делаются копии объектов - копируются указатели.
} // а теперь первоначальные объекты уничтожаются и память под массивы освобождается

main()
{
  pair<IntSet, IntSet> p = intset1.even_odd_division(intset2); // если бы вы обратились к массивам из этой пары, то была бы ошибка

// в конце программы пара уничтожается, вызываются деструкторы и пытаются освободить память, которая освобождена ранее
}

Кроме того у Вас утечки памяти в этих функциях:

IntSet* IntSet::union_(IntSet& object_1) 
{
    IntSet* NewIntSet = new IntSet;
    return NewIntSet;
}
IntSet* IntSet::relative_complement(IntSet& object_1) 
{
    IntSet* NewIntSet = new IntSet;
    return NewIntSet;
}

Вы динамически создаете объекты, но не уничтожаете. Просто программа маленькая и негативные эффекты не успевают возникнуть.
Также, ошибка в деструкторе. Выделяя память под массив - new[], нужно удалять через delete[]

IntSet::~IntSet() {
    delete[] arr_;
}
→ Ссылка