-1

When I'm learning data structure at the binomial heap, I read Weiss's code implementation. Some code as follow:

node implementation and deleteMin algorithm are like:

template<typename Comparable>

struct BinomialNode
{
    Comparable    element;
    BinomialNode *leftChild;
    BinomialNode *nextSibling;
};

void deleteMin( Comparable & minItem )
{   
    int minIndex = findMinIndex( );
    minItem = theTrees[ minIndex ]->element;
    BinomialNode *oldRoot = theTrees[ minIndex ];
    BinomialNode *deletedTree = oldRoot->leftChild;
    delete oldRoot;
}

But I'm confused by the "Comparable & minItem". As we see, the "minItem" saves the element. But soon the "oldRoot" has been deleted! The "element" member is inside of the "oldRoot"! Can someone tell me the principle of the status...

I also made some other tests.

struct Node{
    int i;
    Node * next;
    Node(int i, Node* next = nullptr): i(i), next(next){}
};

void getInt(int & i){
    int * p = new int(3);
    i = *p;
    delete p;   //the reference can get the true value??? =>output: 3(right)
}

void getInt(int * &i){
    int * p = new int(3);
    i = p;
    delete p;   //pointer can't get the real number because of deletion => output: 6904432(wrong)
}

int main()  //for test
{
    Node* child = new Node(3);
    Node* root = new Node(1, child);
    int i;

    getInt(i);
    cout << i << endl;

    int * m; 
    getInt(m);
    cout << *m;
}

I've learnt about the bottom implementation of the reference & is the point *. But why & can get the real value... I feel confused. Thx!!

wind2412
  • 1,011
  • 1
  • 9
  • 24
  • Basically, you aren't *allowed* to access the `int` after `delete`. It so happens that your system isn't clearing that memory yet, but so what, as far as you are concerned, it is gone. You aren't allowed to look and see. This is called [**Undefined Behaviour**](http://en.cppreference.com/w/cpp/language/ub). C++ makes certain things illegal to do, without forcing the cost of checking it every time. Basically, the language won't hold your hand if that would cost you in speed. – BoBTFish Dec 22 '16 at 08:04
  • Um... Another thing I want to ask is whether the reference is safe or not? – wind2412 Dec 22 '16 at 08:07
  • Not sure exactly what you mean, but if you have a reference to something that has been `delete`d, that's UB. Almost exactly the same thing as a dangling pointer. – BoBTFish Dec 22 '16 at 08:09
  • I think so... But as my test above, it is surely the real answer... So I want to know why things go like this... – wind2412 Dec 22 '16 at 08:10
  • Like I said, the system just decided not to pay the cost of blanking out that memory yet. As far as your program is concerned, it is dead and gone. But the compiler writer decided it was more efficient to not return that piece of memory to the operating system yet. Probably the system waits until it has a large amount it can give back all in one go. – BoBTFish Dec 22 '16 at 08:12
  • Got it. Thank you! – wind2412 Dec 22 '16 at 08:13
  • 1
    It is very important to learn **not** to commit Undefined Behaviour. It is easy for your program to **look like** it is working correctly, but actually be broken. You could get subtly wrong results, or a crash, or it would break only when you move to a different computer, or all sorts of problematic outcomes. The worst is when it appears to work perfectly, and only breaks in a couple of years time. – BoBTFish Dec 22 '16 at 08:16
  • Understood. But in fact, the first several lines of codes are from the [Data Structure and Algorithm Analysis in C++ 4th Edition]. Writer is Mark Allen Weiss. I think it is a bit of famous. But he didn't give the erratum of this... So in fact I think ..is there some other problems or not... Because, using pointer I may fail, but when using the reference, it always works... – wind2412 Dec 22 '16 at 08:23
  • 5
    I'm voting to close this question as off-topic because asking for the behavior of undefined behavior is futile. – πάντα ῥεῖ Dec 22 '16 at 08:24
  • Actually, I think that the title is misleading and the question is actually valid. – stefaanv Dec 22 '16 at 08:49
  • @stefaanv Thank you for your comment. Could you tell me something about your idea?:) – wind2412 Dec 22 '16 at 08:55
  • Aha, found the description I was looking for! http://stackoverflow.com/a/6445794/1171191 – BoBTFish Dec 22 '16 at 08:59
  • @BoBTFish: except that the question really is about what happens when you assign to a reference variable. – stefaanv Dec 22 '16 at 09:10
  • @BoBTFish as stefaanv said, it is my misleading title that cause the problem... I am sorry for that. Beside, your website link is perfect :) Thank U all the same ! – wind2412 Dec 22 '16 at 09:26

1 Answers1

0

If you ask whether there is something wrong with the the binomial code, then the answer is no, there is nothing wrong with assigning to the parameter.

In the first code, minItem = theTrees[ minIndex ]->element; copies the object to the object that is passed as reference, so afterwards there is no reference to anything that was deleted (assuming Comparable has no knowledge of BinomialNode). The reference of the parameter refers to the passed object not to anything in the data-structure.

The same goes for the test: after getInt(i), int just contains 3.

However, void getInt(int * &i) returns a dangling pointer, so this is bad code.


Edit out of completeness: the answer was addressing the assumed issue with the reference parameter, but the binomial code void deleteMin( Comparable & minItem ) contains 2 issues, hopefully addressed later in the book:

  1. the case where findMinIndex() fails isn't handled. What happens with an empty heap?

  2. BinomialNode *deletedTree = oldRoot->leftChild;: nothing is done with deletedTree, which at least causes a memory leak and actually loses information.

stefaanv
  • 14,072
  • 2
  • 31
  • 53
  • Thank you for your answer first! But why "copy"? As I know, reference is just like an alias, it is just like "the object itself". So I think it has been deleted... – wind2412 Dec 22 '16 at 08:52
  • 1
    Assigning to a reference does not change what object it references. It changes the value of the object that is referenced. Typically, that means `a = b` stores a copy of `b` into the object referenced by `a`. – Peter Dec 22 '16 at 09:03
  • wind2412: I think your comment shows the confusion in the question. I hope my answer and @Peter's comment solves this. – stefaanv Dec 22 '16 at 09:09
  • Thankful for your explanations! I totally understand all the details. – wind2412 Dec 22 '16 at 09:15
  • You're welcome. Mind you that your question title was misleading, because that was the part that seems to be UB, that most of us picked on. – stefaanv Dec 22 '16 at 09:20
  • I am sorry, but at first what I thought is the title :) So I got a lot of confusion, too. :> – wind2412 Dec 22 '16 at 09:24
  • A little confusion isn't bad. However, I already gave a wrong comment and voted to close the question, when I reread and understood the real question. – stefaanv Dec 22 '16 at 09:29
  • Haha, it doesn't matter. Finally I got the real answer from you, that's okay! – wind2412 Dec 22 '16 at 09:32