2009-11-17 2 views
7

После того как я сделать, скажем,C++ массив удалить Синтаксис оператора

Foo* array = new Foo[N];

Я всегда удалил его таким образом

delete[] array;

Однако, иногда я видел это так:

delete[N] array;

Как мне кажется, компилировать и работать (по крайней мере, в msvc2005), интересно: Каков правильный способ сделать это? Почему он компилирует другой способ?

ответ

13

Вы можете проверить эту ссылку MSDN: delete[N] operator. Значение игнорируется.

EDIT Я попробовал этот пример кода на VC9:

int test() 
{ 
    std::cout<<"Test!!\n"; 
    return 10; 
} 

int main() 
{ 
    int* p = new int[10]; 
    delete[test()] p; 
    return 0; 
}; 

Выход: Тест !!

Таким образом, выражение оценивается, но возвращаемое значение игнорируется. Я удивлен, если не сказать больше, я не могу придумать сценарий, почему это требуется.

+0

+1. полезная информация –

+0

означает, что вы можете удалить массив [2N]; и что бы скомпилировать –

+0

Спасибо, это то, что я искал. – raven

4

Правильный способ - сделать delete[] array;. Я даже не знал, что delete[N] array; будет компилироваться (и я сомневаюсь, что это должно).

+1

Он компилируется на VC9 с предупреждением C4208: используется нестандартное расширение: delete [exp] - exp оценивается, но игнорируется. Я не понимаю, что это значит. – Naveen

+1

Это означает, что код (1) недействителен C++ и (2) выражение 'N' оценивается, но игнорируется. Это довольно неуместно, но описывает, что произойдет, если вы написали 'delete [N ++] array;' - N сначала увеличилось, а затем проигнорировалось. – MSalters

+0

Действительно, его сначала игнорируют, а затем увеличивают :) – raven

5

Независимо от того, является ли второй случай правильным или нет, я бы рекомендовал использовать первый, поскольку он менее подвержен ошибкам.

Visual Studio компилирует много вещей, которые он не должен делать.

+4

«Visual Studio компилирует много вещей, которые он не должен». Аминь. – sbi

10

delete [N] array недействителен. Он не определен в стандарте C++: раздел 5.3.5 определяет выражение delete либо delete expr, либо delete [] expr, и ничего больше. Он не компилируется на gcc (версия 4.1.2). Что касается того, почему он компилируется в Visual C++: обратитесь в Microsoft.

+0

Какой стандарт C++? И у вас есть ссылка/ref, где ее можно найти? – Kissaki

+1

@ Kissaki: Я бы имел в виду C++ 03, который не доступен на законных основаниях онлайн. Однако формулировка очень похожа на C++ 11, проект которой доступен по адресу http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf –

+0

А, спасибо .. – Kissaki

-2

если это работает, это нестандартное расширение.

delete [] array; 

- правильная форма.

delete array; 

иногда также работает, но зависит от реализации (таким образом, неправильно).

+1

Поведение второй формы (без скобок) четко определено для указателей без массива. Его поведение для массивов - нет. Во всяком случае, я думаю, это причина, почему кто-то проголосовал за вас. –

+1

'delete array' не« работает »в каком-либо смысле этого слова, если вы не имеете в виду, что он не разбивает программу. Он не будет восстанавливать всю память, выделенную в первую очередь, и если она не сбой, она будет запускать деструктор только для первого объекта в массиве. (Который также является ошибкой, если вы сделали 'new Foo [0]'.) – Bill

+1

@Bill: Мне жаль, что я не могу проголосовать за комментарии. Иногда ваше утверждение может быть правдой, а иногда это может и не быть. См. Здесь: http://stackoverflow.com/questions/1553382/1553407#1553407 и мой комментарий здесь: http://stackoverflow.com/questions/1553382/1553391#1553391 – sbi

4

Первый пункт: практически нет оснований использовать форму массива new или delete для начала - вместо этого используйте std :: vector (или какой-либо другой контейнер).

Во-вторых: назад в темные века C++ вам нужно было указать размер массива, который вы удаляли, поэтому, если вы использовали x = new T[N], то соответствующее совпадение было delete [N] x. Требование явно указать размер было удалено long назад, но некоторые компиляторы (особенно те, которые заботятся о обратной совместимости с древним кодом) все еще позволяют это.

Если вам действительно не нужно оставаться совместимым с древним компилятором (которому 20 лет или около того), вы не должны его использовать. Опять же, если вам не нужно оставаться совместимым с таким старым компилятором, он не поддерживает стандартные контейнеры, вы не должны использовать форму массива new или delete в первую очередь. Просто остановись!

+0

Спасибо за урок истории. Тогда, если бы мне пришлось передать динамический массив, скажем, поплавков, в сторонний libray, что было бы правильным способом сделать это со стандартными контейнерами? – raven

+0

Используйте вектор. Когда вам нужно передать адрес/длину, используйте & vec [0] и vec.size(). –

+0

+1: В черновике стандарта sep '94 синтаксис уже был «delete []». И в том же году Design and Evolution (p218) прокомментировал, что этот синтаксис «... оказался слишком подверженным ошибкам, поэтому бремя отслеживания количества элементов было поставлено на реализацию». –

Смежные вопросы