Итераторы ничего не копируют.В терминах C они ведут себя почти как указатели в массиве.
Однако вы копируете элементы здесь:
void PopulateList( void )
{
ItemToBeFound *masterItem = new ItemToBeFound( NULL /* no refItem */ );
myList.push_back( *masterItem ); //copy of masterItem pointee
ItemToBeFound *slaveItem = new ItemToBeFound( masterItem ); //initialized with masterItem, which does not point to the object stored in the list!
myList.push_back( *slaveItem ); //copy of slaveItem pointee, also stores masterItem, but not object from the list
//slaveItem is leaked here, masterItem is only kept via slaveItem copy in the list
}
Если вы инициализируете такие объекты, ваши подчиненные объекты никогда не сохраняют указатели на объектыв списке, а скорее к объектам, созданным с помощью new
.
Давайте пошагово пройдемся по коду (здесь я буду резиновым отладчиком):
ItemToBeFound *masterItem = new ItemToBeFound( NULL /* no refItem */ );
Вы размещаете объект в куче (у них нет имен, но давайте назовем его m1
) и указатель на стек, называемый masterItem
, поэтому разыменованный masterItem
в точности равен m1
.
myList.push_back( *masterItem );
std::list::push_back()
создает копию данного аргумента (я игнорирую семантику перемещения - они здесь не используются).Обратите внимание на аргумент - разыменованный masterItem
или m1
, как мы его ранее называли.
Копия объекта m1
, созданного push_back
, будет называться m2
Так что теперьу нас есть следующее (с a->b
означает a
указывает на b
):
masterItem->m1
myList->m2
Следующая строка:
ItemToBeFound *slaveItem = new ItemToBeFound( masterItem );
Здесь выинициализировать slaveItem
новым объектом в куче - s1
.
masterItem->m1
myList->m2
slaveItem->s1->masterItem->m1 (s1 points to masterItem, which points to m1)
Последний:
myList.push_back( *slaveItem );
И снова push_back()
создает копию своего аргумента в куче(эта копия будет называться s2
)
masterItem->m1
slaveItem->s1->masterItem->m1
myList->m2
myList->s2->masterItem->m1
В конце концов у вас есть:
- 4 объекта в куче:
m1
, m2
, s1
и s2
(все типа ItemToBeFound
) - 2 объекта в стеке:
masterItem
и slaveItem
(оба типа указателя) - один объект в глобальной области:
myList
(здесь можно рассматривать как объект стека) m2
и s2
хранятся в myList
и могут быть повторены в - Оба
s1
и s2
имеют указатели на m1
- Нет подчиненного объекта указывает на
m2
Позже, когда вы запускаете mainFunction()
, объект m2
заполняется данными, но объект s2
пытается получить данные из m1
, которые не были заполнены какими-либо значимымиdata.
Трудно предложить какое-либо решение без дополнительной информации.Если бы я не смог реорганизовать структуру классов, я бы использовал вместо нее std::list<std::shared_ptr<ItemToBeFound>>
, что обеспечит безопасность ваших указателей и сохранит только std::weak_ptr<ItemToBeFound> referenceItem
в подчиненных объектах (чтобы избежать циклических зависимостей и четко объявить владельца).
Вы могли бы иметь std::list<ItemToBeFound*>
и управлять памятью вручную, но это противоречит духу современного C ++ и должно использоваться с большой осторожностью - поток может занять больше веток в C ++, чем в C, и все их сложнее отслеживатьна delete
все.
Вы можете технически хранить в подчиненных объектах указатели на объекты, хранящиеся в списке (или даже на итераторы к ним), но это похоже на странное решение.Вы не контролируете эти объекты и не владеете ими, поэтому вам не следует сохранять на них указатели.