为什么我可以在boost::fibonacci_heap中更新弹出的元素?
Why can I update a popped out element in a boost::fibonacci_heap?
我正在使用boost::fibonacci_heap库实现快速行进算法,并且我开始使用它们的句柄操作元素。
我已经写了下面的基本代码,它编译得很好,但我不明白它的行为:
首先将每个push元素的句柄存储在数组中。然后从堆中取出第一个元素,检查堆大小是否减小了。
但随后我尝试使用其句柄更新弹出的元素的值。这个操作成功了(令人惊讶吗?),更新后的元素现在位于堆的顶部。但是堆大小保持不变,因为我没有正确地压入一个新元素。
那么,当一个弹出的元素被更新并放回堆中时,会发生什么呢?堆是否仍然有效?
# include <boost/heap/fibonacci_heap.hpp>
# include <iostream>
using namespace std;
using namespace boost::heap;
struct node
{
int index;
double time;
node(const int& i, double t) : index(i), time(t) {}
};
struct compare_node
{
bool operator()(const node& n1, const node& n2) const
{
return (n1.time > n2.time);
}
};
int main()
{
fibonacci_heap< node, compare<compare_node> > heap;
typedef fibonacci_heap< node, compare<compare_node> >::handle_type handle_t;
handle_t tab_handle[10];
int n;
double tt[10];
// assign a set of arbitrary numbers to initialise array tt:
tt[0] = 5.3;
tt[1] = 0.25;
tt[2] = 3.6;
tt[3] = 1.75;
tt[4] = 9.1;
tt[5] = 2.54;
tt[6] = 3.8;
tt[7] = 6.1;
tt[8] = 1.23;
tt[9] = 7.32;
// push the values of tt into the heap, and keep track of the handle of each element in the heap:
for (n=0; n<10; n++)
{
tab_handle[n] = heap.push(node(n, tt[n]));
}
// display first element in heap
cout << "first element in heap is :" << heap.top().index << " " << heap.top().time << "n";
// check size of the heap
cout << "size of heap is :" << heap.size() << "n";
// remove top element
heap.pop();
// check size of the heap
cout << "size of heap after pop is :" << heap.size() << "n";
// display first element in heap
cout << "first element in heap is now :" << heap.top().index << " " << heap.top().time << "n";
// access value of a given element by index:
cout << "element index 2 has time :" << (*tab_handle[2]).time << "n";
// attempt to access the element with handle tab_handle[1]: this element was actually popped out of the heap previously. But I can access it:
cout << "element index 1 has time :" << (*tab_handle[1]).time << "n";
// update the time of an element using its handle. This is quite standard.
heap.update(tab_handle[2],node(2, tt[2]/10));
// but now I can also update the element that was popped out of the heap:
heap.update(tab_handle[1],node(1, tt[1]/10));
// display first element in heap
cout << "first element in heap is now :" << heap.top().index << " " << heap.top().time << "n";
// check size of the heap
cout << "size of heap after pop is :" << heap.size() << "n";
return 0;
}
终端输出:
first element in heap is :1 0.25
size of heap is :10
size of heap after pop is :9
first element in heap is now :8 1.23
element index 2 has time :3.6
element index 1 has time :0.25
first element in heap is now :1 0.025
size of heap after pop is :9
确实,您正在调用未定义行为。
在valgrind¹下运行程序:
sehe@desktop:/tmp$ valgrind --db-attach=yes ./test
==14185== Memcheck, a memory error detector
==14185== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==14185== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==14185== Command: ./test
==14185==
first element in heap is :1 0.25
size of heap is :10
size of heap after pop is :9
first element in heap is now :8 1.23
element index 2 has time :3.6
==14185== Invalid read of size 8
==14185== at 0x400F21: main (test.cpp:47)
==14185== Address 0x5aa6d78 is 24 bytes inside a block of size 72 free'd
==14185== at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==14185== by 0x402789: __gnu_cxx::new_allocator<boost::heap::detail::marked_heap_node<node> >::deallocate(boost::heap::detail::marked_heap_node<node>*, unsigned long) (new_allocator.h:110)
==14185== by 0x401D2C: boost::heap::fibonacci_heap<node, boost::heap::compare<compare_node>, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_>::finish_erase_or_pop(boost::heap::detail::marked_heap_node<node>*) (fibonacci_heap.hpp:745)
==14185== by 0x4015E7: boost::heap::fibonacci_heap<node, boost::heap::compare<compare_node>, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_, boost::parameter::void_>::pop() (fibonacci_heap.hpp:398)
==14185== by 0x400E1C: main (test.cpp:34)
==14185==
==14185==
==14185== ---- Attach to debugger ? --- [Return/N/n/Y/y/C/c] ----
看,你正在读取先前删除的内存。哎呀。
任何事都可能发生。发生什么取决于你的运气,你的电脑等。
¹我使用了一个清理过的代码版本:Live On Coliru,所以你可以交叉引用行号
相关文章:
- 更新的矢量元素不打印
- C++:添加新结构时,结构指针向量中的所有元素都会更新
- 对的排序向量 (std::vector<pair<int, int>>) 按对的第一个元素搜索并更新第二个元素值
- 为什么在功能内擦除元素后不列出更新?
- 在删除之前更新一组元素指针中的元素
- 为什么我的矢量不随我对其元素所做的更改而更新
- 如何在C++中从一个向量元素减去std::unorderede_map向量元素并更新它
- 在函数中删除第一个元素后,如何更新链接列表的phead
- 插入新元素时结束迭代器会获得更新
- 更新模型/视图方案中 QXXXView (QTableView, QTreeView,..) 元素的显示工具提示
- 删除和更新矢量<struct>中的特定元素
- 如何更新std :: Priority_queue中的元素
- 如何更新最近在 std::vector<pair<int, int>> 中输入的元素?
- 对一个具有重复元素的数组进行排序时更新并行数组
- 通过指针更新矢量的元素
- 正在更新微小Xml元素中的数据
- 如何更新映射C++中元素的值
- 为向量成员和更新元素指定默认值
- 如何在ListModel中添加元素后更新QML ListView
- 不使用 if 插入/更新 std::unordered_map 元素的最快方法是什么