Простое тестовое приложение:
cout << new int[0] << endl;
выходы:
0x876c0b8
Итак, похоже, что это работает. Что говорит об этом стандарт? Всегда ли законно "распределять" пустой блок памяти?
Простое тестовое приложение:
cout << new int[0] << endl;
выходы:
0x876c0b8
Итак, похоже, что это работает. Что говорит об этом стандарт? Всегда ли законно "распределять" пустой блок памяти?
Из 5.3.4/7
Когда значение выражения в direct-new-declarator равно нулю, функция распределения вызывается для выделения массива без элементов.
Из 3.7.3.1/2
Эффект разыменования указателя, возвращаемого как запрос нулевого размера, составляет undefined.
Кроме
Даже если размер запрашиваемого пространства [новым] равен нулю, запрос может выйти из строя.
Это означает, что вы можете это сделать, но вы не можете юридически (четко определенным образом на всех платформах) разыменовывать память, которую вы получаете, - вы можете передать ее только в массив delete - и вы должны удалить ее.
Вот интересная нотная заметка (а не нормативная часть стандарта, но включена для пояснительных целей), прилагаемая к предложению из 3.7.3.1/2
[32. Цель состоит в том, чтобы реализовать оператор new(), вызвав malloc() или calloc(), поэтому правила в основном одинаковы. С++ отличается от C, требуя нулевого запроса, чтобы вернуть ненулевой указатель.]
Да, законно выделять такой массив нулевого размера. Но вы также должны удалить его.
Что говорит об этом стандарт? Всегда ли законно "распределять" пустой блок памяти?
Каждый объект имеет уникальный идентификатор, т.е. уникальный адрес, который подразумевает ненулевую длину (реальный объем памяти будет постепенно увеличиваться, если вы запрашиваете нулевые байты).
Если вы выделили более одного из этих объектов, вы обнаружите, что у них разные адреса.
Да, вполне законно выделять блок 0
с new
. Вы просто ничего не можете с ним поделать, поскольку для доступа к ним нет действительных данных. int[0] = 5;
является незаконным.
Однако, я считаю, что стандарт позволяет таким вещам, как malloc(0)
возвращать NULL
.
Вам все равно понадобится delete []
любой указатель, который вы получите обратно из распределения.
Любопытно, что С++ требует, чтобы оператор new возвращал законный указатель даже когда запрашиваются нулевые байты. (Требование об этом нечетном звучании поведение упрощает работу в другом месте на языке.)
Я нашел эффективное С++ Third Edition, как это описано в "Item 51: придерживайтесь соглашения при записи нового и удаления".