Давай рассмотрим, для начала, строку под комментарием.
ArrayArray[0] = *new Array<int>{10};
Что тут происходит.
ArrayArray[0] вернет ссылку на
Array<int>.
*new Array<int>{10} выделяет память в куче под
Array<int>, вызывает инициализатор
Array<int>::Array(int length), после чего делает разыменование получившегося указателя на
Array<int>.
После этого для подготовленной ссылки на
Array<int> будет выполнен оператор копирования по умолчанию, функциональность которого просто скопирует поля из объекта справа в объект слева от присвоения.
После этого результат
new Array<int>{10} становится утекшим, т.к. указатель на него сразу становится потерян и освободить занимаемую им память становится невозможно.
Именно поэтому с этой строчкой у тебя "всё отрабатывает нормально". И нет, всё у тебя не отрабатывает нормально потому что память утекла.
Давай рассмотрим следующую строку.
ArrayArray[0] = Array<int>{10};
Что тут происходит.
ArrayArray[0] вернет ссылку на
Array<int>.
Array<int>{10} инициализирует безымянный локальный объект на стеке, используя инициализатор
Array<int>::Array(int length).
После этого выполняется уже оператор перемещения по умолчанию, суть которого снова сводится к копированию полей из объекта справа в объект слева. После этого оба объекта ссылаются на одну и ту же выделенную память через поле
T *m_data.
Далее безымянный локальный объект уничтожается, освобождая недавно выделенную память. А
ArrayArray[0] в этот момент начинает ссылаться на освобожденную память.
Double deletion происходит тогда, когда
ArrayArray в конце работы программы пытается удалить уже освобожденную память в
ArrayArray[0].
В твоем коде на лицо нарушение
инварианта типа.
Что нужно сделать.
Тебе должно уже стать понятно что проблема в твоем коде связана с поведением операторов копирования и перемещения по умолчанию. Но проблема у тебя, на самом деле, значительно шире. Потому что завтра ты ведь точно захочешь еще и инициализацию копией провести или вернуть объект по значению из функции. В этом случае тебя тоже ждут проблемы.
Решением твоих проблем будет соблюдение
правила 3/5/0.
Тебе нужно полноценно описать поведение объектов при копировании, перемещении, а так же при инициализации копией и инициализацией через перемещение.