Если я сделаю что-то вроде:
void foo() {
bar* b2 = new bar();
b2 = new bar();
}
Что происходит с первым значением строки, инициализированным new
? Переписывается ли оно вторым назначением или удаляется с помощью ключевого слова delete заранее?
Вы должны вызвать delete
для первого b2
прежде чем назначать новое значение b2
. Второй вызов действительно перезапишет значение в b2
(которое является адресом объекта, созданного в первом new
).
Другими словами, ваш код имеет утечку памяти, потому что первый объект bar
"потерян".
Это утечка памяти. C++ выделил место для вашего объекта, а затем вы потеряли все ссылки на него, поэтому он будет сидеть там, пока остальная часть ваших программ не будет бесполезной и голодной.
Поэтому в C++ обычно предпочитают не использовать new
.
void foo() {
bar b2 = bar();
b2 = bar();
}
особенно в ситуациях, когда вы хотите использовать переменную только в 1 области, выделение ее в стеке является гораздо более безопасным выбором. Особенно в случае исключений
Foo foo = new Foo();
...
delete foo;
небезопасно, что, если ...
выдает исключение? Тебя утечка! Если вы хотите использовать семантику безопасности и указателя в C++ 11
unique_ptr<bar> b2;
если вам действительно нужна семантика указателя. Теперь, когда все ссылки на b2
будут потеряны, он удаляется сам. Примечание. Циклы все еще не сломаны и не протекают.
Если вы создаете что-то с new
вы должны освободить его с удалением, иначе утечка памяти будет там. Чтобы предотвратить утечку, вы должны написать:
void foo() {
bar* b2 = new bar();
delete b2;
b2 = new bar();
}
В вашей первой строке есть три "вещи".
Учитывая это разделение, очевидно, что вы назначаете два значения по одной переменной. Поскольку вам нужна эта переменная, чтобы удалить объект, который вы потеряли после перезаписи первого назначенного значения. Это одна из ситуаций "утечки памяти".
Перед вами перезаписать переменную b2
, вы должны думать о первом экземпляре объекта класса bar
. Если это больше не требуется, используйте delete
для удаления объекта. Если вам все еще нужно, сделайте копию указателя.
Ваша первая строка:
bar* b2 = new bar()
будет выделять комнату sizeof(bar)
в свободном хранилище (а также вызвать конструктор) и дать вам адрес этого устройства, скажем, 0x123, это означает, что b2 запоминает 0x123.
Но теперь вы перезаписываете свой b2 - теперь он указывает на новое местоположение, данное вам новым. Это означает, что вы больше не можете связаться с более старым блоком памяти, который был назначен первым новым вызовом.
bar
жив, но потерян. Это называется «утечка памяти». Все, что вы делаете, это указывает указателюb2
на новую переменную.