Как перенести узлы между двумя объектами boost::intrusive::slist
Допустимо ли передавать узлы между двумя boost::intrusive::slist<boost::intrusive::cache_last<true>>
объекты? Что-то вроде следующего
auto one = boost::intrusive::slist<Node, boost::intrusive::cache_last<true>>{};
auto two = boost::intrusive::slist<Node, boost::intrusive::cache_last<true>>{};
auto node = std::make_unique<Node>();
one.push_back(*node);
auto& front = one.front();
one.pop_front();
two.push_back(front);
Я получаю ошибку сегментации и ошибку подтверждения с буст-версией 1.70.0 https://wandbox.org/permlink/nWHakTYUiVBGKH6I. Как я могу это исправить?
Примечание: я не могу выделить новый узел и скопировать старый, потому что я использую навязчивый список, чтобы контролировать, когда и где происходит распределение.
1 ответ
Вы удаляете узел, когда он все еще находится в контейнере - режим безопасного соединения проверяет это и будет подтвержден.
Если вы сначала удалите контейнер (измените порядок построения объекта) или если вы удалите узел из контейнера перед очисткой, утверждения не будет.
например
auto node = std::make_unique<Node>();
auto one = boost::intrusive::slist<Node, boost::intrusive::cache_last<true>>{};
auto two = boost::intrusive::slist<Node, boost::intrusive::cache_last<true>>{};
one.push_back(*node);
auto& front = one.front();
one.pop_front();
two.push_back(front);
Это кажется целью splice
метод:
Эффекты: переносит все элементы списка x в этот список до элемента, на который он указывает. Деструкторы или конструкторы копирования не вызываются.
two.splice(two.end(), one, one.begin());
Полностью рабочая демоверсия:
#include <iostream>
#include <string>
#include <boost/intrusive/slist.hpp>
struct Node : public boost::intrusive::slist_base_hook<>
{
int i;
std::string s;
Node(int i, std::string s) : i(i), s(std::move(s)) {}
};
using NodeList = boost::intrusive::slist<Node, boost::intrusive::cache_last<true>>;
int main()
{
NodeList one;
NodeList two;
auto show = [&](auto text){
std::cout <<text <<"\n one\n";
for (auto & item : one) { std::cout <<" " <<item.i <<' ' <<item.s <<'\n'; }
std::cout <<" two\n";
for (auto & item : two) { std::cout <<" " <<item.i <<' ' <<item.s <<'\n'; }
};
one.push_back(*new Node(42, "hello"));
show("before splice");
two.splice(two.end(), one, one.begin());
show("after splice");
one.clear_and_dispose([](Node * ptr){ delete ptr; });
two.clear_and_dispose([](Node * ptr){ delete ptr; });
return 0;
}
При запуске напишу:
before splice
one
42 hello
two
after splice
one
two
42 hello