2010-12-03 4 views
3

Я только начала свой контейнерный класс и я уже имеют вопросы:ошибка в классе деструкторе

class Container 
{ 
    private: 

    string* BasePointer; // The starting pointer. 
    unsigned int Capacity; // The number of values the container can hold. 

    public: 

    Container() // Default constructor. 
    { 
     Capacity = 1; 
     BasePointer = new string[Capacity]; 
    } 

    ~Container() // Destructor. 
    { 
     delete BasePointer; // Delete the container to prevent memory leaking. 
    } 
}; 

я получаю ошибку Container Classes(26467) malloc: *** error for object 0x100100088: pointer being freed was not allocated. Что я делаю неправильно?

+1

Это называется * деструктор *, как в уничтожении. Не деконструктор. :) – jalf 2010-12-03 15:30:23

+0

@jalf Правильно, извините. – Maxpm 2010-12-03 17:09:48

ответ

7

XXX ptr = new XXX[size] следует сопоставлять с массивом версии delete [] ptr, а не только с обычным delete.

Читайте о free store management на C++, и, как напоминает нам Джеймс, следуйте за rule of three в таких случаях.

4

вы должны использовать удалить []

delete[] BasePointer; 
1

Привет, если вы создаете массив, который вы должны использовать удалить [] BasePointer;

0

Чтобы быть более явным, чем другие, когда вы используете тип массива, вам нужно удалить указатель, используя delete[].

Это происходит не только при использовании new T[size], рассмотрим следующий образец:

typedef int T[42]; 
int* x = new T; 
delete[] x; // needs delete[] though you used new without [] 

На общей ноте, если ваш объект «владеет» объект он держит через указатель, вы должны рассмотреть возможность использования умный указатель (например, boost :: scoped_array). Таким образом, вам не нужно беспокоиться о деконструкции, что происходит, когда исключение брошено, реализуя задание оп и конструктора копирования ...

упомянули
2

Других, что у вас есть несоответствующие new[] с delete, и вы должны изменить delete к delete[], чтобы исправить это. Однако это только первая из ваших проблем.

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

{ 
    Container c1; 
    Container c2(c1); 
} // c2.~Container(); // frees the memory pointed to by 'BasePointer' 
    // c1.~Container(); // also frees the memory pointed to by 'BasePointer'. 

С BasePointer членом обеих c1 и c2 указывает на тот же массив, он получает в два раза освобожден.

Есть несколько проще в использовании альтернативы:

  • Рассмотрим с помощью std::vector в любом месте вы могли бы использовать динамически выделенный массив. Поскольку ваш класс называется Container, я предполагаю, что вы пытаетесь реализовать контейнер для владения ресурсом, поэтому, возможно, вы не хотите его использовать.

  • Рассмотрите возможность использования boost::scoped_ptr или std::unique_ptr (если ваш компилятор поддерживает его) для управления правом собственности на указатель. Обе эти функции подавляют создание неявно объявленного конструктора копирования, заставляя вас реализовать свои собственные, если вы на самом деле пытаетесь их использовать.

Даже если вы реализуете Container, вы все равно должны воспользоваться более примитивными контейнеров делать тяжелую работу за вас (или, по крайней мере, переописать эти примитивные контейнеры так, что тяжелая атлетика консолидируется в небольшой набор утилит).

Наконец, в качестве стилистической точки вам не нужно использовать malloc для контейнера. Стандартная библиотека предоставляет std::allocator, которая может использоваться для выделения пространства для и построения объектов.

Смежные вопросы