Начиная с C ++ 11, генерация неявно определенного конструктора не рекомендуется (по уважительной причине), если в классе есть пользовательский деструктор, но он все еще генерируется. Этот конструктор копирования просто скопирует size
и data
, создавая неглубокую копию, а не глубокую. Это дорога к катастрофе, потому что data
будет удаляться несколько раз, когда исходный объект и его копии будут уничтожены.
Например, если вы запустите исходный код под Valgrind , вы увидите следующий отчет:
==9908== HEAP SUMMARY:
==9908== in use at exit: 0 bytes in 0 blocks
==9908== total heap usage: 3 allocs, 4 frees, 73,733 bytes allocated
==9908==
==9908== All heap blocks were freed -- no leaks are possible
==9908==
==9908== For counts of detected and suppressed errors, rerun with: -v
==9908== ERROR SUMMARY: 18 errors from 9 contexts (suppressed: 0 from 0)
Если вы хотите, чтобы Data
был копируемым Вы должны предоставить конструктор глубокого копирования, который выделяет новое хранилище и копирует в него данные. Тот, что в вашем вопросе выглядит почти (*) нормально:
==9993== HEAP SUMMARY:
==9993== in use at exit: 0 bytes in 0 blocks
==9993== total heap usage: 4 allocs, 4 frees, 73,738 bytes allocated
==9993==
==9993== All heap blocks were freed -- no leaks are possible
==9993==
==9993== For counts of detected and suppressed errors, rerun with: -v
==9993== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Если вам вообще не нужна конструкция копирования, вы можете отключить ее неявную генерацию, явно удалив ее:
Data(const Data&) = delete;
То же самое верно для оператора копирования. неявно определенный не будет делать то, что вы хотите. Не забудьте об этом.
(*) Обратите внимание, что other.data
может быть nullptr
, поэтому вам необходимо проверить его перед копированием:
void* memcpy(void* dest, const void* src, std::size_t count);
Если либо dest
, либо src
является нулевым указателем, поведение не определено, даже если count
равно нулю.