C ++ - Выделение памяти в куче с помощью «нового» - PullRequest
7 голосов
/ 29 января 2011

Если у меня есть следующее утверждение:

int *x = new int;

В этом случае я динамически распределяю память в куче.Другими словами, теперь у меня есть reserved адрес памяти для int объекта.

Скажите после этого, что я сделал следующее:

delete x;

Это означает, что я freed up адрес памяти в куче.

Скажу после этого я снова сделал следующее:

int *x = new int;

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

Что если я сделал это до delete:

x = NULL;

И затем сделал это:

int *x = new int;

Будет ли x указывать адрес памяти в куче другой , чем старый?

Спасибо.

Ответы [ 6 ]

10 голосов
/ 29 января 2011

В первом случае вы могли бы снова получить тот же блок памяти, но в этом нет уверенности.

Во втором случае, поскольку вы не освободили память, есть почти уверенность, что вы получите другой блок памяти по другому адресу. Есть сборщики мусора C ++. Если вы использовали один из них, вполне возможно, что сборщик мусора будет работать между временем, когда вы обнулили указатель (так что у вас больше не было доступа к ранее выделенному блоку памяти), и снова запросом выделения. В таком случае вы можете снова получить тот же блок памяти. Конечно, без сборщика мусора вы просто теряете память, поэтому вы никоим образом не можете это сделать.

2 голосов
/ 29 января 2011

То, что вы спрашиваете, полностью не определено (согласно стандарту C / C ++) и будет зависеть от реализации.

вам должно быть легко проверить это с вашей версией компилятора.

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

Что касается того, что, я думаю, может произойти, вы, скорее всего, получите тот же адрес, ЕСЛИ У вас нет других потоков в вашей программе, которые также выделяются в это же время.Но даже тогда вы можете получить один и тот же адрес, если конкретная реализация malloc вашего компилятора решит использовать разные кучи для разных потоков (что лучше с точки зрения производительности)

1 голос
/ 29 января 2011

1) После освобождения, если вы снова выделите ту же переменную, нет гарантии, что вы получите тот же кусок памяти.Подумайте, как реализовано новое, это можно сделать любым способом, который вы можете себе представить, даже используя пользовательские распределители.Также возможно, что другой поток использовал new между вызовами free () и new () и «украл» вашу память

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

1 голос
/ 29 января 2011

Когда вы делаете это перед удалением:

x = NULL;

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

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

Не ожидайте получить тот же самый новый адрес после удаления, затем новый снова. Хотя это может происходить время от времени, случайно.

1 голос
/ 29 января 2011

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

1 голос
/ 29 января 2011

Нет, такой гарантии нет.Это полностью зависит от распределителя, используемого для удовлетворения вашего запроса памяти.Тем не менее, C ++ является мощным зверем, поэтому переопределим новый оператор.Вы можете создать собственный распределитель (управление памятью), который обеспечивает память определенным образом, что иногда очень полезно.

...