Подтвердить что ты не робот

С++: push_back (новый объект()) утечка памяти?

Является ли следующий код С++ утечкой памяти?

list.push_back(new String("hi"));

Как я понимаю, push_back из любой std collection/container всегда делает копию. Итак, если новая строка будет скопирована, ничто не сможет удалить строку new'd правильно? поскольку после push_back нет ссылки на него...

Я верен или ошибаюсь здесь?

Спасибо.

JBU

edit: Я думаю, что я ошибаюсь, поскольку new вернет указатель... мы всегда будем иметь указатель, чтобы иметь возможность удалить новую строку

4b9b3361

Ответ 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