С++: push_back (новый объект()) утечка памяти?
Является ли следующий код С++ утечкой памяти?
list.push_back(new String("hi"));
Как я понимаю, push_back из любой std collection/container всегда делает копию. Итак, если новая строка будет скопирована, ничто не сможет удалить строку new'd правильно? поскольку после push_back нет ссылки на него...
Я верен или ошибаюсь здесь?
Спасибо.
JBU
edit: Я думаю, что я ошибаюсь, поскольку new вернет указатель... мы всегда будем иметь указатель, чтобы иметь возможность удалить новую строку
Ответы
Ответ 1
Нет, указатели векторных магазинов и копия сделаны из указателя. Вы можете удалить объект в любое время позже.
(Вы можете получить утечку, если в заявлении произойдёт выброс исключения, и вы не поймаете и не обработаете его должным образом. Поэтому вы можете использовать интеллектуальные указатели.)
Ответ 2
Да, но не по той причине, о которой вы думаете.
В зависимости от того, как list
определяется и инициализируется, push_back
может вызвать исключение. Если это так, указатель, возвращаемый из new
, будет потерян и никогда не сможет быть освобожден.
Но при условии, что push_back
возвращается успешно, он сохраняет копию указателя, возвращаемого new
, и поэтому мы можем освободить память позже, вызвав delete
на этой копии, чтобы не было утечки памяти, если вы правильно звоните delete
.
Ответ 3
Если бы я увидел этот код, я был бы очень подозрительным, возможно утечка памяти. На поверхности, по-видимому, добавляется выделенный String*
в list<String*>
. По моему опыту, за этим часто следует плохой код обработки ошибок, который неправильно освобождает выделенную память.
Хотя это опасно во многих случаях, это не обязательно утечка памяти. Рассмотрим следующий пример:
class Container {
~Container() {
std::list<String*>::iterator it = list.begin();
while (it != list.end()) {
delete *it;
it++;
}
}
void SomeMethod() {
...
list.push_back(new String("hi"));
}
std::list<String*> list;
}
В этом коде нет утечки, потому что содержащий класс отвечает за выделенную память и освободит ее в деструкторе.
ИЗМЕНИТЬ
Как заметил асеплер, все еще существует утечка, если метод push_back
выдает исключение.
Ответ 4
Вы правы, если ничто не удаляет строку, когда она удалена из списка.
Ответ 5
Да, это утечка памяти позволяет вам как-то предпринять шаги для удаления содержащихся указателей.
И лучший способ добиться этого - использовать интеллектуальный указатель. Например, Boost shared_ptr или С++ 0x shared_ptr.
Ответ 6
Нет.
Вы можете удалить объект, выполнив следующие действия:
delete list[i];
list.erase(list.begin() + i);
или очистить весь список:
for (unsigned int i = 0; i < list.size(); ++i)
{
delete list[i];
}
list.clear();
Ответ 7
list.push_back(new String("hi"));
Почему вы выделяете динамические строки в первую очередь? Если вы не хотите общаться между различными частями вашей программы, изменяя строки (что было бы довольно необычно), избавьтесь от указателя:
std::list<std::string> list; // note: no pointer!
list.push_back(std::string("hi")); // explicitly create temporary
list.push_back("hi"); // alternative: rely on coercion