Глава 7. Указатели и ссылки__________________________________769

освобождение. Хуже того, сложно быть уверенным в правильном вызове операции delete. Как объяснялось в главе 6, вызовы new и delete должны быть парными; если вы вместе с new используете операцию массива ([]), то следует использовать ее и с delete, а это будет трудно проконтролировать после выхода из функции. Другая проблема состоит в том, чтобы отследить размер этого массива; утрата его грозит выходом за границы массива.

Представьте, что вы хотите использовать массив объектов, динамически создаваемый внутри функции, поскольку точное количество элементов его при разработке неизвестно. Разумно будет передать размер массива в функцию как аргумент, выделить с помощью операции new память для него, поработать с ним (зная его размер), а затем память освободить. Если вы отложите удаление массива до какой-то точки за пределами функции, то сохранение информации о размере массива станет делом проблематичным. Такое программирование чревато ошибками.

Замечание

Примечательным исключением является функция strdup (из С), которая выделяет участок памяти, достаточный для хранения символьного массива — строки ASCIIZ. Это безопасно, поскольку размер массива, т. е. длина строки легко определяется по символу \0 в конце строки.

Эта функция сопровождается комментарием, предупреждающим вас о том, что ответственность за удаление этого массива (вызовом функции free) лежит на вашей совести.

Функция strdup использует функцию malloc, поэтому память следует освобождать функцией free. Что произойдет, если вы будете смешивать использование new и delete с malloc и free — неизвестно, это означает, что вы можете основательно сесть в галошу.

Вот как может быть устроена функция, возвращающая указатель на блок памяти, выделенный внутри функции (применительно к символьному массиву):

//Не делайте этого, если вы не уверены твердо в своих действиях char *ReturnCharPointer( unsigned int size) { return new char[size]; )

Еще хуже, если вы выделяете память при помощи new, но забываете ее освободить и к тому же не возвращаете указатель. Продемонстрируем эту ситуацию на примере массива вещественных чисел:

// для size используется аргумент по умолчанию

void ArrayOfFloats( unsigned int size = 10)

{

float *farray = new float[size];

// некий код