2016-06-16 5 views
0

Я работаю с тем же кодом из этого code from my previous SO post, но я внес несколько изменений. Моя проблема в том, что у меня есть динамический массив, который я вызываю delete[] внутри моей перегрузки оператора для конструктора копирования, и я получаю ошибку ниже.Удалить [] вызывает сбой в C++

Исключение, брошенное в 0x0F7063BB (ucrtbased.dll) в Lab3.exe: 0xC0000005: Место обнаружения нарушения доступа 0xCCCCCCBC.

Если для этого исключения имеется обработчик, программа может быть безопасно продолжена.

Может ли кто-нибудь помочь мне понять, почему? Я проверил связанные вопросы, но есть разные ошибки, чем из того, что я вижу, и я не нашел результата в моем поиске в Google. Я использую C++ 11 на визуальной студии 2015.

#include "ListArray.h" 

template < typename DataType > 
List<DataType>::List (int maxNumber) 
{ 
    //maxSize = MAX_LIST_SIZE; maybe??? 
    maxSize = maxNumber; 
    dataItems = new DataType[maxSize]; 
    size = maxSize - 1; 
    cursor = 0; // sets cursor to the first value in list 
    for (; cursor <= size; cursor++) 
     dataItems[cursor] = 1; 
    cursor = 0; 
} 

template < typename DataType > 
List<DataType>::List (const List& source) 
{ 
    *this = source; // should be handled by copy constructor 
} 

template < typename DataType > 
List<DataType>& List<DataType>::operator= (const List& source) 
{ 
    if (this != &source) 
    { 
     maxSize = source.maxSize; 
     size = source.size; 
     cursor = source.cursor; 
     delete []dataItems; // clears dataItems, weird run-time error here. Why? 
     dataItems = new DataType[size]; 
     for (int count = 0; count < size; count++) 
      dataItems[count] = source.dataItems[count]; 
    } 
    else 
     // do nothing, they are the same so no copy is made 
     return *this; 
} 

template < typename DataType > 
List<DataType>::~List() 
{ 
    maxSize = 0; 
    size = 0; 
    cursor = -1; 
    delete[] dataItems; 
} 

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

+0

'if (cursor = size - 1)' Вы уверены, что это условие с назначением верно? – MikeCAT

+1

Ошибка возникает из-за того, что перед инициализацией используется 'dataItems'. Попробуйте инициализировать его до '* this = source;' – MikeCAT

+0

Нет, но мой код даже не доходит так далеко.Он не проходит мимо функции operator =, потому что я тестирую их по порядку – Callat

ответ

2

Если вы собираетесь использовать оператор присваивания для создания своих копий, вам нужно создать пустой объект, иначе operator= потерпит неудачу, когда он попытается очистить старое содержимое перед его заменой (как пояснил Сэм в его ответ и MikeCAT упомянули в его комментарии - дайте им upvotes - и что Dieter told you on your earlier question).

Поскольку C++ 11, конструктор цепочки ака делегирования конструктора можно, например:

template < typename DataType > 
List<DataType>::List (const List& source) 
    : List() /* default construct object before proceeding */ 
{ 
    *this = source; // should be handled by copy constructor 
} 

другой вариант, чтобы сделать конструктор копирования отвечает за создание самого объекта по умолчанию, и это то, что было бы необходимо в C++ 98 и C++ 03:

template < typename DataType > 
List<DataType>::List (const List& source) 
    : maxSize(0), dataItems(NULL), size(0) // initialize members 
{ 
    *this = source; // should be handled by copy constructor 
} 

Но это дублирует функцию конструктора по умолчанию, так что до тех пор, как ваш компилятор поддерживает функции C++ 11, предпочитают называть существующий.

Детали делегирования конструктора ... усложняются. Между прочим, обычно любое исключение, созданное внутри конструктора объекта, предотвращает существование объекта, и деструктор не вызывается. Когда делегирование используется, тогда объект становится живым, когда какой-либо конструктор завершается, а исключение внутри конструктора обертки встречается с уже живым объектом и вызывает деструктор для вас. Такое поведение может быть или не быть желательным, но это то, на что нужно обратить внимание, потому что безопасность исключений важна в современном C++.

+1

Хорошая точка re: конструкторы безопасности и цепочки исключений. – SergeyA

+0

ЭТО! Реализация этого исправленного моего кода полностью благодарит вас, сэр! – Callat

2

Конструктор копирования не инициализирует ничего в новом экземпляре класса. Все, что он делает, - это вызов оператора присваивания.

Оператор присваивания выполняет:

delete []dataItems; 

Поскольку dataItems не был инициализирован, это приводит к неопределенному поведению, а также немедленный крах.

+0

Я не понимаю, что вы имеете в виду, ничего не инициализируется. Если мой другой конструктор существует выше, то не создается '* this', а затем передается копируемой копии? – Callat

+0

@Hikari: Конструкторы только подобъектов получают неявно. Если вы хотите, чтобы один из ваших конструкторов (конструктор копирования) вызывал другой (конструктор по умолчанию), вы должны сказать компилятору, чтобы он это сделал. Прямо сейчас ваш конструктор копий начинается с необработанной памяти, содержимое которой является случайным, а затем сразу вызывает 'operator =()' –

+0

Можете ли вы привести пример того, как я буду это делать? Будет ли это список инициализации? – Callat

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