对象的成员变量的意外更改

时间:2014-06-21 04:32:05

标签: c++ oop data-structures

我在C ++中有这段代码:

void printHeap (Heap<T> &heap)
{
    typename list< HeapNode<T> >::iterator heapIterator = heap.heap.begin();

    for( ; heapIterator != heap.heap.end(); ++heapIterator)
    {
        cout<<"element"<<endl;
    }
}

这是堆的定义:

template <class T>
class Heap
{

public:

    list <HeapNode<T> > heap;
    HeapNode<T> *minValue;

    BinomialHeap(HeapNode<T> *min = 0)
    {
        minValue = min;
    }

    T getMinimumKey()
    {
        return minValue->key;
    }

    void insert(T data)
    {
        HeapNode<T> tmp (data);
        heap.push_back(tmp);
        if(!minValue || minValue->key > tmp.key)
            minValue = &tmp;
    }
};

HeapNode.cpp 模板

class HeapNode
{
public:
    int degree;
    HeapNode<T> *parent;
    list <HeapNode<T> *> sons;
    T key;
    HeapNode(T d, HeapNode<T> *parent = 0)
    {
        key = d;
        this->parent = parent;
        degree = 0;
    }
};

我尝试过这段代码,但是我得到了一些意想不到的值:

BinomialHeap<int> heap;
heap.insert(4);
heap.insert(3);
heap.insert(2);
heap.insert(1);
cout<<heap.getMinimumKey() <<endl;
printHeap(heap);
cout<<heap.getMinimumKey();

第一个cout打印1(如预期的那样),但是在调用printHeap之后,即使我没有操作这个成员变量(第二个cout打印一个奇怪的数字),minValue也会改变。为什么会这样?它不应该打印相同的数字,因为我没有在该方法中修改minValue吗?

2 个答案:

答案 0 :(得分:2)

void insert(T data)
{
    HeapNode<T> tmp (data);
    heap.push_back(tmp);
    if(!minValue || minValue->key > tmp.key)
        minValue = &tmp;
}

此代码已损坏。您创建一个临时对象,然后存储指向它的指针。但是一旦函数返回,对象就不再存在,因此指针指向任何东西。当你致电getMinimumKey时,你会得到垃圾。我想您希望将minValue设置为指向您推送到列表中的tmp副本。

答案 1 :(得分:1)

  

但在调用printHeap之后,minValue会更改

这通常表示您正在进行越界数组访问,或通过无效指针访问。

void insert(T data)
{
    HeapNode<T> tmp (data);
    heap.push_back(tmp);
    if(!minValue || minValue->key > tmp.key)
        minValue = &tmp;
}

这里是...... tmp是此函数的本地函数,当函数退出时它不再存在,将minValue作为一个野指针。

要解决这个问题,只要minValue没有改变,你就必须使minValue指向保证不会被销毁的东西;或以其他方式实施您的minvalue-finder。

可以使minValue指向一个实际的列表元素,但是这仍然很危险,除非您还在列表可能有节点的每个可能的其他点检查minValue从中删除。您还必须在copy-constructor和copy-assignment运算符中考虑minValue;这些的默认版本将不再有效(它们会再次将minValue作为伪指针)。