Простое тестовое приложение:
cout << new int[0] << endl;
выходы:
0x876c0b8
Похоже, это работает. Что стандарт говорит об этом? Всегда ли законно «выделять» пустой блок памяти?
Простое тестовое приложение:
cout << new int[0] << endl;
выходы:
0x876c0b8
Похоже, это работает. Что стандарт говорит об этом? Всегда ли законно «выделять» пустой блок памяти?
Ответы:
От 5.3.4 / 7
От 3.7.3.1/2
Также
Это означает, что вы можете сделать это, но вы не можете юридически (четко определенным образом на всех платформах) разыменовать полученную память - вы можете только передать ее в удаление массива - и вы должны удалить ее.
Вот интересная сноска (то есть не нормативная часть стандарта, но включенная в пояснительных целях), приложенная к предложению из 3.7.3.1/2
источник
new[]
сdelete[]
- независимо от размера. В частности, когда вы вызываете,new[i]
вам нужно немного больше памяти, чем той, которую вы пытаетесь выделить, чтобы сохранить размер массива (который позже используетсяdelete[]
при освобождении)Да, это законно, чтобы выделить массив нулевого размера, как это. Но вы также должны удалить его.
источник
int ar[0];
это незаконно, почему новое хорошо?sizeof (type)
ожидается, что никогда не вернет ноль. См. Например: stackoverflow.com/questions/2632021/can-sizeof-return-0-zeroКаждый объект имеет уникальную идентичность, то есть уникальный адрес, который подразумевает ненулевую длину (фактический объем памяти будет незаметно увеличен, если вы запросите нулевые байты).
Если вы выделите более одного из этих объектов, вы обнаружите, что они имеют разные адреса.
источник
operator []
также где-то хранит размер массива (см. isocpp.org/wiki/faq/freestore-mgmt#num-elems-in-new-array ). Таким образом, если реализация выделяет счетчик байтов для данных, она может просто выделить счетчик байтов и 0 байтов для данных, возвращая указатель 1-last-last.operator new[]
должны возвращать разные указатели. Кстати,new expression
есть некоторые дополнительные правила (5.3.4). Я не смог найти никакой подсказки, чтоnew
с размером 0 на самом деле требуется что-то выделить. Извините, я понизил голос, потому что обнаружил, что ваш ответ не отвечает на вопросы, но дает некоторые противоречивые утверждения.new[]
реализация могла бы возвращать адреса в диапазоне, где нет сопоставленной динамической памяти, следовательно, фактически не используя какую-либо память (при использовании адресного пространства)while(!exitRequested) { char *p = new char[0]; delete [] p; }
цикл без повторного использования указателей, может превратиться в пыль, прежде чем он может исчерпать адресное пространство, но на платформе с 32-разрядными указателями, которая будет гораздо менее разумное предположение.Да, это совершенно законно, чтобы выделить
0
размерный блок сnew
. Вы просто не можете сделать что-нибудь полезное с этим, так как для вас нет действительных данных.int[0] = 5;
незаконноОднако я считаю, что стандарт допускает такие вещи, как
malloc(0)
возвращениеNULL
.Вам все равно понадобится
delete []
указатель, который вы получите от распределения.источник
Я обнаружил, что третье издание Effective C ++ говорит так: «Статья 51: придерживайтесь соглашения при написании нового и удалении».
источник
Я гарантирую вам, что новый int [0] стоит вам дополнительного места, так как я его протестировал.
Например, использование памяти
значительно меньше, чем
Использование памяти второго фрагмента кода минус использование первого фрагмента кода - это память, используемая для многочисленных новых int [0].
источник