Размер динамически распределенного массива

Верно ли, что указатель, назначенный стартовому адресу динамически выделенного массива, не имеет информации о размере массива? Поэтому мы должны использовать другую переменную для хранения ее размера для последующей обработки массива с помощью указателя.

Но когда мы освобождаем динамически выделенный массив, мы не указываем размер, вместо этого мы просто "free ptr" или "delete [] ptr". Как можно удалить или удалить информацию о размере массива? Можем ли мы использовать ту же схему, чтобы избежать сохранения размера массива в другой переменной?

Спасибо!

Ответы

Ответ 1

Да, это правда.

delete знает размер блока памяти, потому что new добавляет дополнительную информацию в кусок (обычно до области, возвращенной пользователю), содержащий его размер, а также другую информацию. Обратите внимание, что все это очень специфично для реализации и не должно использоваться вашим кодом.

Итак, чтобы ответить на ваш последний вопрос: Нет - мы не можем его использовать - это деталь реализации, которая сильно зависит от платформы и компилятора.


Например, в распределителе выборки примеров, продемонстрированном в K & R2, это "заголовок", помещенный перед каждым выделенным фрагментом:

typedef long Align; /* for alignment to long boundary */

union header { /* block header */
  struct {
    union header *ptr; /* next block if on free list */
    unsigned size; /* size of this block */
  } s;

  Align x; /* force alignment of blocks */
};

typedef union header Header;

size - размер выделенного блока (который затем используется free или delete).

Ответ 2

Самое смешное, что исторически это было delete [20] arr; так же, как и arr = new int[20]. Однако практика доказала, что информация о размере может безболезненно храниться распределителем, и поскольку большинство людей, использующих ее, затем сохраняли ее в любом случае, она была добавлена ​​к стандарту.

Что более забавно и малоизвестно, так это тот факт, что этот "расширенный синтаксис удаления" фактически поддерживается несколькими компиляторами С++ (несмотря на то, что они ошибочны даже перед стандартом С++ 98), хотя ни один из них не требует он.

int* arr = new int[20];
delete [20] arr;

Печальная часть этого всего, однако, заключается в том, что нет стандартного способа получения этого переданного размера для вашего собственного использования: -/

Ответ 3

Верно, что массив не содержит размер массива, вы должны сохранить эту информацию позже. При удалении массива через delete или free это указатель на выделенную память, которую вы передаете. Менеджер памяти, используемый (либо системой, либо собственным пользовательским интерфейсом от переопределения новых и удаленных), знает освобожденную область памяти и отслеживает ее. Надеюсь, что это имеет смысл.

Ответ 4

Да, это правда. Это часть того, почему вы редко пытаетесь справиться с этим напрямую и вместо этого используете стандартный контейнер. Единственный раз, когда имеет смысл справляться с этим, - если вы сами решили реализовать контейнер (в этом случае вы обычно отслеживаете информацию о размере в своей реализации контейнера).