我正在用C ++为数据结构类构建一个模板化的Max Heap类。该实现演示了一个带有矢量引擎盖的Max Heap。有一个与作业相关的在线提交,当我提交我的时,所有的测试(推,弹,顶部和大小)通过和工作(对于在线未知的单元测试以及我写的所有)和我有我的任何测试都没有内存泄漏,但是我在线提交的内存泄漏部分失败了,向我表明我的Bubble Up(Reheap Up)或Bubble Down(Reheap Down)算法正在做一些有趣的矢量索引。 / p>
我注意到我经常使用括号运算符来处理向量,所以我通过并将所有括号更改为.at()
,这样我就可以看到任何被抑制的越界错误。据称,除了记忆泄漏外,还有飞行的颜色。然后我认为可能其中一个单元测试正在添加太多的值,因为某些未知的原因,向量无法清除所有值...因为我在我的最大堆类中向向量添加了这么多值,所以不是这样的在我的单元测试中,花了90秒才完成,在完成所有52K分配之后,还进行了52K解除分配,并且valgrind报告没有错误。
下面是该类的一些主要代码,如果有人可以决定编写某些代码的位置,在某些情况下可能会保证内存泄漏会很棒!
template <class T>
class MaxHeap {
public:
MaxHeap(){
// TODO: Fill me in
}
~MaxHeap() {
data.clear();
}
void push(T value){
data.push_back(value);
bubbleUp(data.size()-1, value);
}
void pop(){
if(!size()) {
return;
}
T val = data.at(size()-1);
data.pop_back();
if(!size()) {
return;
}
data.at(0) = val;
bubbleDown(0, val);
}
T top(){
if(!data.size()) throw logic_error("Empty Heap");
return data.at(0);
}
unsigned int size(){
return data.size();
}
void print_vec() {
for (int i = 0; i < size(); ++i) {
cout << data.at(i) << " ";
}
cout << endl;
}
vector<T> getVec() {
return data;
}
private:
vector<T> data;
void bubbleUp(int idx, T value) {
int position = idx;
int parent_idx = parent(position);
while (data.at(parent_idx) < value) {
data.at(position) = data.at(parent_idx);
data.at(parent_idx) = value;
position = parent_idx;
parent_idx = parent(position);
}
}
void bubbleDown(int idx, T value) {
int left_child_idx = left_child(idx);
int right_child_idx = right_child(idx);
int max_child_idx;
if(left_child_idx <= size()-1) { // left child (consequently right child) in bounds of vector
if(left_child_idx == size()-1) { // no right child, left is maxchild
max_child_idx = left_child_idx;
} else {
max_child_idx = (data.at(left_child_idx) <= data.at(right_child_idx)) ? right_child_idx : left_child_idx;
}
if(data.at(idx) < data.at(max_child_idx)) {
data.at(idx) = data.at(max_child_idx);
data.at(max_child_idx) = value;
bubbleDown(max_child_idx, value);
}
}
}
int left_child(int idx) {return (idx*2+1);}
int right_child(int idx) {return (idx*2+2);}
int parent(int idx) {return ((idx-1)/2);}
};
答案 0 :(得分:1)
警告:这只是一个理论,因为泄漏源不可能在此处显示的代码中。
如果T swap; // initialized to something. perhaps using new
while (data.at(parent_idx) < value) {
swap = data.at(parent_idx); //assume no delete in T.operator=()
data.at(parent_idx) = value;
data.at(position) = swap;
position = parent_idx;
parent_idx = parent(position);
}
是一个格式错误的类型,在使用赋值运算符时不会释放它的内存,那么这可能是触发这个不良行为的部分:
T
这不是此代码中的问题。但是,您可能仍然可以在此处进行修补。为什么在循环外定义while (data.at(parent_idx) < value) {
T swap = data.at(parent_idx); // no assignment here
data.at(parent_idx) = value;
data.at(position) = swap;
position = parent_idx;
parent_idx = parent(position);
}
?
while (data.at(parent_idx) < value) {
data.at(position) = std::move(data.at(parent_idx));
data.at(parent_idx) = value;
position = parent_idx;
parent_idx = parent(position);
}
===
不相关但更好 - 不要使用不必要的中间变量,并混合移动语义:
{{1}}