C++: является ли push back (new Object ()) утечкой памяти?
следующий код C++ утечка памяти?
list.push_back(new String("hi"));
Как я понимаю, push_back из любой коллекции/контейнера std всегда делает копию. Итак, если новая строка скопирована, ничто не может удалить новую строку правильно? поскольку после push_back нет ссылки на него...
Я прав или ошибаюсь здесь?
спасибо.
Jbu
edit: я думаю, что ошибаюсь, так как new вернет указатель...у нас всегда будет указатель, чтобы иметь возможность удалить новую строку
7 ответов
нет, вектор хранит указатели и копия указателя. Вы можете удалить объект в любое время.
(вы можете получить утечку, если оператор случайно выдаст исключение, и вы не поймаете и не обработаете его должным образом. Вот почему вы можете рассмотреть возможность использования смарт-указателей.)
да, но не по той причине, вы думаете.
в зависимости от того, как list
определяется и инициализируется,push_back
может бросить исключение. Если это так, указатель возвращается из new
теряется, и никогда не смогут освободиться.
но если push_back
возвращает успешно, он сохраняет копию указателя, возвращенного new
, и поэтому мы можем освободить память позже, вызвав delete
на этой копии, так что нет утечки памяти, пока вы do вызов delete
правильно.
если бы я увидел этот код, я был бы очень подозрителен, что возможна утечка памяти. На поверхности кажется, что он добавляет выделенный 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
метод бросает исключение.
Да, это утечка памяти unles вы каким-то образом предпринимаете шаги для удаления содержащихся указателей.
и лучший способ сделать это-использовать смарт-указатель. Например, shared_ptr Boost или shared_ptr C++0x.
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
нет.
Вы можете удалить объект, выполнив:
delete list[i];
list.erase(list.begin() + i);
или очистить весь список по:
for (unsigned int i = 0; i < list.size(); ++i)
{
delete list[i];
}
list.clear();