2017-07-22 1 views
0

Ich mache eine sehr einfache Übung auf C++ - Rekursion zum rekursiven Umkehren eines Stapels. Der Code ist unten angehängt. Mein Problem ist, ob ich Referenz T & oder einfach T in meinem rekursiven Aufruf putToBottom verwenden sollte (Stapel &, const T &).C++ Referenz in Rekursion (reverse einen Stapel)

#include <iostream> 
#include <stack> 
using namespace std; 

template <typename T> 
void putToBottom(stack<T>& myStack, const T& topOne) 
{ 
    if (myStack.empty()) 
    { 
     myStack.push(topOne); 
     return; 
    } 

//Should I use T& or T here??? 
    ***T temp = myStack.top();*** 
    myStack.pop(); 
    putToBottom(myStack, topOne); 
    myStack.push(temp); 
} 

template <typename T> 
void reverseStack(stack<T>& myStack) 
{ 
    if (myStack.empty()) return; 
    T& topOne = myStack.top(); 
    myStack.pop(); 
    reverseStack(myStack); 
    putToBottom(myStack, topOne); 
} 

int main() 
{ 
    stack<int> myStack; 
    myStack.push(1); 
    myStack.push(2); 
    myStack.push(3); 
    myStack.push(4); 
    reverseStack(myStack); 
    while (!myStack.empty()) 
    { 
     cout << myStack.top() << "\n"; 
     myStack.pop(); 
    } 
    cout << endl; 
    return 0; 
} 

Wenn ich schreibe T temp = myStack.top();, erhalte ich die richtige Antwort (der Stapel ist jetzt 1 (oben) -> 2 -> 3 -> 4). Wenn ich jedoch T& temp = myStack.top(); oder const T& temp = myStack.top(); schreibe, bekomme ich den falschen (der Stapel wird 4 (oben) -> 4 -> 4 -> 4). Irgendwelche Ideen würden helfen! Vielen Dank!

+1

Wenn Sie 'T &' verwenden, ruft es ein undefiniertes Verhalten auf, weil 'myStack.pop()' die Referenz ungültig macht. Verwenden Sie C++ 11? Wenn dem so ist, dann ist die Bewegungssemantik wahrscheinlich das, was Sie wollen. – Arcinde

Antwort

0

Wenn Sie T& temp = myStack.top() verwenden, dann wird myStack.pop(), temp wird eine dangling Referenz und es ist undefiniertes Verhalten, es weiter zu verwenden.

Wenn Sie 11 ++ verwenden C dann wollen Sie wahrscheinlich Semantik bewegen:

T temp = std::move(myStack.top()); 
myStack.pop(); 
putToBottom(myStack, topOne); 
myStack.push(std::move(temp)); 

Und in ähnlicher Weise in reverseStack.

Obwohl ich beachten muss, ist dies eine besonders ineffiziente Möglichkeit, einen Stapel umzukehren. Besser wäre es einfach, alles vom ursprünglichen Stapel zu entfernen, während man es auf einen zweiten Stapel schiebt.

+0

Danke für Ihre Antwort! Aber leider habe ich den Punkt nicht verstanden, warum ich eine hängende Referenz bekam ... Selbst wenn der Stapel den obersten Gegenstand herausspringt, ist der Gegenstand noch im Umfang lebendig. Dann denke ich, meine Temp-Variable sollte noch gültig sein, oder? Vielleicht habe ich etwas Wichtiges verpasst ... Irgendwelche Ideen würden helfen! Danke. –

+0

Nur weil es im Umfang ist, bedeutet es nicht, dass es gültig ist. Sie binden 'myStack.top()' an den Verweis 'temp', aber dieser Verweis verlängert die Lebensdauer des Objekts nicht. Wenn Sie 'myStack.pop()' aufrufen, wird der Destruktor 'T :: ~ T()' des Objekts aufgerufen und der Speicher, der verwendet wird, um ihn im 'std :: stack' zu speichern, kann freigegeben werden. Ihr Verweis 'temp' könnte jetzt auf einen nicht zugewiesenen Speicher verweisen, und die Verwendung dieses Verweises ist UB. – Arcinde

+0

Oh ... Ich habe nicht in die Implementierung von Pop() geschaut ... Danke dir soooo viel! –