2016-09-17 2 views
0

Я новичок в std :: shared_ptr и std :: set. Для следующего кода я хочу знать, как я могу удалить ребро из edge_.Удаление края из ребер_, которое объявляется как std :: set <std :: shared_ptr <Edge>> edge_;

edge_ объявлен как std::set<std::shared_ptr<Edge>> edges_;, и я хочу удалить ребро, на которое ссылается общий указатель, хранящийся в std :: set. Мой код для части здесь, но, похоже, проблема.

auto findEdge = findLinkingNode1->second->edges_.find(edge); 
findLinkingNode1->second->edges_.erase(findEdge); 

Ошибка:

test8c(3034,0x7fff78df2000) malloc: *** error for object 0x7f8553403350: pointer being freed was not allocated 
*** set a breakpoint in malloc_error_break to debug 
Abort trap: 6 

Как я могу удалить ребро из edges_, который управляется с помощью общих указателей, учитывая, что общие указатели хранятся в станд :: набор?

+0

Вы должны проверить возврат из поиска, если он не был успешным. Кроме этого, был ли указатель сохранен в общем указателе, который вы пытаетесь уничтожить, выделенном в куче? Как это было выделено? –

+0

Являются ли «пограничные» полиморфными или содержат большие объемы данных? Если нет, то зачем вообще использовать общие указатели? Ценностная семантика может быть большой победой. –

+0

Кромка, которая хранится в edge_, является общим указателем. Он преобразуется из края в общий указатель через std :: make_shared. «new» не использовался, чтобы сделать объект, на который указывают указатели, поэтому он не выделяется на кучу, я думаю.Что касается краев, да, они полиморфны, то общий шаблонный класс Graph используется с шаблоном функции для разных типов, а узловые и краевые структуры являются частью этого класса графа. – iteong

ответ

1

Это только гадать, но, учитывая код вы предоставляете ...

auto findEdge = findLinkingNode1->second->edges_.find(edge); 
findLinkingNode1->second->edges_.erase(findEdge); 

... Я бы сказал, что ваша проблема в том, что вы стираете edges_.end()which is not allowed (вероятно, неопределенное поведение):

The iterator pos must be valid and dereferenceable. Thus the end() iterator (which is valid, but is not dereferencable) cannot be used as a value for pos.

Переменная findEdge будет равна edges_.end(), если данный edge не был найден в комплекте. Чтобы найти элемент, std::set использует Compare объект, тип которого определяется с помощью второго параметра шаблона ...

std::set<std::shared_ptr<Edge>> edges_; 

... которые вы не указали, что это недобросовестный std::less<std::shared_ptr<Edge>>, который в свою очередь вызывает the operator< of the shared pointer, которые ...

Note that the comparison operators for shared_ptr simply compare pointer values; the actual objects pointed to are not compared.

... не сравнивает объекты, а только указатели. Поэтому, если указатели, используемые для вставки и поиска, не указывают на точно такое же (как в идентичном, не только «равном») объекте, вы зарегистрировались на наличие проблем.


Выше было предположение, но учитывая Ваш комментарий ...

findOrig->second->edges_.insert(std::make_shared<Edge>(Edge (findOrig->second, findDest->second, val))); 

... делает это факт, так как там нет (почти) нет возможности достать указатель, возвращаемый make_shared.

Внедрите класс сравнения для вашего набора, который сравнивает фактические объекты Edge. (Избавление от указателей не так просто, потому что вы сказали, что Edge является полиморфным)

Мораль: всегда проверяйте возможные ошибки.

+0

Итак, класс сравнения, о котором вы говорите, заключается в том, что для возможности удаления края из edge_? Почему возврат, возвращаемый make_shared, не может быть возвращен вообще? Так что я не могу удалить край вообще? – iteong

+0

Параметр 'edge' для функции find должен быть таким же (или его копией) в качестве указателя, возвращаемого' make_shared' в вызове insert. Как вы получаете «edge», то есть что ему назначено? –

+0

Вы имеете в виду, что находится внутри класса краев? Это как указано выше. – iteong

Смежные вопросы