при заполнении std::vector по значению будут ли удалены динамически выделенные указатели объектов?

Возможный дубликат:
Почему вызывает ли использование «нового» утечки памяти?

Я новичок в STL, и я читал, что хорошей практикой обычно является сохранение векторов объектов, а не векторов указателей на объекты. В попытке соответствовать этому кредо я столкнулся со следующим сценарием:

//Approach A
//dynamically allocates mem for DD_DungeonRoom object, returns a pointer to the block.
//then, presumably, copy-constructs the de-referenced DD_DungeonRoom as a 
//disparate DD_DungeonRoom object to be stored at the tail of the vector
//Probably causes memory leak due to the dynamically allocated mem block not being
//caught and explicitly deleted
mvLayoutArray.push_back(*(new DD_DungeonRoom()));

//Approach B
//same as A, but implemented in such a way that the dynamically allocated mem block
//tempRoom can be deleted after it is de-referenced and a disparate DD_DungeonRoom is
//copy-constructed into the vector
//obviously rather wasteful but should produce the vector of object values we want
DD_DungeonRoom* tempRoom = new DD_DungeonRoom();
mvLayoutArray.push_back(*(tempRoom));
delete tempRoom;

первый вопрос: в подходе А возникает утечка памяти?
второй вопрос: если предположить, что А вызывает утечку памяти, решает ли Б ее? третий вопрос: есть ли (или, что более вероятно, «что есть») лучший способ добавить объекты пользовательского класса (например, требующие динамического распределения через «новый» или «malloc») в вектор по значению?

спасибо, CCJ


person CCJ    schedule 09.01.2013    source источник
comment
Он будет просачиваться, потому что использование новых причин утечки памяти"> stackoverflow.com/questions/8839943/   -  person Luchian Grigore    schedule 09.01.2013


Ответы (3)


первый вопрос: в подходе А возникает утечка памяти?

да.

второй вопрос: если предположить, что A вызывает утечку памяти, решает ли B ее?

Да, но это глупое решение. И небезопасно в том случае, если конструктор копирования DD_DungeonRoom или vector::push_back выдает исключение.

третий вопрос: есть ли (или, что более вероятно, «что есть») лучший способ добавить объекты пользовательского класса (например, требующие динамического распределения через «новый» или «malloc») в вектор по значению?

Никакие объекты в C++ не требуют динамического выделения памяти. Просто добавьте объекты прямо в вектор, вызвав конструктор, без new.

mvLayoutArray.push_back(DD_DungeonRoom());

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

myLayoutArray.emplace_back();
person Benjamin Lindley    schedule 09.01.2013
comment
хм, я не знал, что push_back(‹constructor›) является допустимым синтаксисом. Что ж, это упрощает и значительно улучшает дело! - person CCJ; 09.01.2013
comment
@CCJ: Да, C ++ намного проще и красивее, если вы выбросите идеи Java из головы. - person Benjamin Lindley; 09.01.2013

Подход А вызывает утечку, да. Подход B не подходит, но поскольку все, что вы делаете, это выделяете объект в куче, помещаете копию в вектор, а затем удаляете его, вы могли бы в этом случае точно так же сделать:

DD_DungeonRoom tempRoom;
mvLayoutArray.push_back(tempRoom);

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

Кроме того, если вам любопытно, произойдет ли утечка памяти, есть много хороших инструментов, чтобы попробовать это и посмотреть, что произойдет. valgrind — один из очень простых в использовании примеров.

person Mattias Nilsson    schedule 09.01.2013

если ваша единственная проблема с aproch A — это утечка памяти, почему бы не использовать вектор shared_ptr?

person qPCR4vir    schedule 09.01.2013
comment
Потому что у него есть накладные расходы, которые не нужны для его ситуации. - person Benjamin Lindley; 09.01.2013
comment
Больше накладных расходов, чем создание каждого только для копирования в вектор, а затем уничтожения? это зависит от размера или стоимости строительства DD_DungeonRoom. или? - person qPCR4vir; 09.01.2013
comment
shared_ptr добавляет немного больше сложности, чем я думаю, что мне нужно в данный момент; очевидно, что подход B не является хорошим производственным решением, а скорее помогает прояснить мое замешательство. Предложение @BenjaminLindley лучше всего подходит для моей ситуации. - person CCJ; 09.01.2013
comment
В ПОРЯДКЕ. Теперь я не уверен, но проверьте, можете ли вы извлечь выгоду из конструкции перемещения-копии или чего-то подобного. - person qPCR4vir; 09.01.2013