Подтвердить что ты не робот

Почему * должен * удалить [] и удалить быть другим?

Мне хорошо известно, что в С++, что delete[] соответствует new[], delete соответствует new. Речь идет не о синтаксисе С++. Мне интересно, почему причины delete[] были определены как нечто отличное от простого delete. Каковы причины реализации этого?

Рассмотрим, что происходит с этим кодом:

MyClass *object = new MyClass;
delete object;

Когда встречается delete, менеджер памяти должен искать значение указателя объекта в своей структуре распределения, независимо от того, что он есть, и помечать соответствующий блок памяти sizeof(MyClass) как свободный.

Теперь рассмотрим, что происходит с этим кодом:

MyClass *array = new MyClass[ num_objects ];
delete [] array;

Когда встречается delete, менеджер памяти должен искать значение указателя массива в своей структуре распределения, независимо от того, что это такое, найти num_objects значение из этой структуры и пометить соответствующий num_objects*sizeof(MyClass) фрагмент памяти как бесплатный.

Помимо num_objects предполагается 1 в одном объекте и просматривается во внутренней структуре данных в массиве, я не вижу разницы. Итак, почему delete и delete[] не могли быть написаны одинаково?

Другими словами, что не так с

MyClass *object = new MyClass;

реализуется как

MyClass *object = new MyClass[1];

так что синтаксис С++ не должен делать различия между delete и delete[]?

4b9b3361

Ответ 1

В принципе, они могут быть реализованы одинаково. Тем не менее, есть затраты на хранение количества элементов где-то, итерацию по этим элементам и вызов деструктора для каждого (как по времени, так и по пространству).

Одна из основных философий С++ - "не платите за то, что вы не используете". Поскольку существует дополнительная стоимость, связанная с программами распределения и перераспределения на основе массива, которые программисты могут не захотеть платить, язык явно делает эти две операции отдельными.

Надеюсь, это поможет!

Ответ 2

Во-первых, функциональность new/delete отличается от функциональности new[]/delete[]. Первый может использоваться для выполнения полиморфного выделения и полиморфной делеции. Последнее не поддерживает полиморфизм вообще. Массивы в С++ не являются полиморфными, только отдельные объекты. Вероятно, можно с силой свести эти две функциональности в одну, чтобы разрешить полиморфное удаление отдельных объектов и по-прежнему не допускать полиморфное удаление массивов, но оно не будет выглядеть красиво.

Во-вторых, как вы, вероятно, знаете, типичная реализация new[] будет хранить точное количество объектов в выделенном массиве, которое будет использоваться позже delete[], чтобы вызвать нужное количество деструкторов. Однако в большинстве современных реализаций возникает проблема не сохранять размер массива, когда выделенный тип имеет тривиальный деструктор.

Почему они это делают? Они делают это, чтобы сохранить память, т.е. Избежать сохранения размера, когда его можно избежать. Обратите внимание, что они справляются со всей этой проблемой даже в ситуациях, когда относительная потеря памяти обычно невелика (одно поле size_t по сравнению с массивом объектов).

Таким образом, очевидно, что этот способ экономии памяти считается целесообразным.

При таких обстоятельствах очевидно, что это должно быть даже более ценным в ситуациях, когда размер массива известен точно как 1, то есть с этой точки зрения реализация new T через new T[1] была бы чрезвычайно расточительной.