Ясное дело, что по Стандарту вызовы malloc()/free()*, **new/delete и new[]/delete[] должны быть строго парными, иначе неопределенное поведение.
Хотя я и видел в очень крупных и серьезных проектах что-то вроде:
float *f = new float[count];
// ...
delete f;
Разработчики обосновывали такую запись так: мол, тип элементарный, деструктора не имеет, можно делать delete и не париться, за несколько лет разработки с этим ни разу не возникло проблем.
...но мы-то с вами знаем, что это неопределенное поведение, и в очередную пятницу тринадцатого компилятор решит скомпилировать код запуска всех ядерных ракет...
Меня беспокоит пара других вопросов:
1)
Type *f = new Type[1];
delete f;
Это неопределенное поведение?
2)
struct Type
{
int a, b, c;
float values[10];
};
Type *f = new Type[count];
free(f);
Даже если Type не содержит деструктора и динамических данных, например, если это структура/класс из нескольких объектов элементарных типов, это все равно неопределенное поведение?
Формально - да, неопределенное, так как для выделения вызывается оператор new
для массива, пусть и из одного элемента, а delete
- нет.
Уж это точно неопределенное, потому как new/delete
и malloc/free
вообще могут использовать разные механизмы работы с памятью.
"По-моему, так." (с) Пух
1.
На первый взгляд в этом примере:
Type *f = new Type[1];
delete f;
Компилятор может понять, что запрашивается один элемент.
Но в общем случае оператор new не анализирует количество запрашиваемых элементов массива хотя бы потому, что в общем случае это количество может быть известно только в рантайме. Поэтому
Type *f = new Type[1];
delete f;
однозначно неправильно. Ведь на месте единицы может быть переменная, значение которой вводит пользователь.
Например:
int size;
cin>>size;
Type *f = new Type[size];
delete f;
Однозначно нельзя запрашивать память new а освобождать free. Это вообще из другой оперы. Парный оператор для new это delete.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Хорошим тоном в C/C++ считается использование const везде, где можно