C ++对象在for循环后得到一个残值

时间:2016-02-02 15:37:18

标签: c++ class oop

我为队列创建了一个类,我在循环中使用该类的对象。在迭代之后,队列中第一个元素的值变为残值。为什么这样,我该如何解决? 这是.h文件:

#ifndef QUEUE_H
#define QUEUE_H

#include "headers.h"

template <class T> 
class Queue
{
    public:

        Queue();
        ~Queue();

        void Push(T value);                                     // Insert a new element at the end of the queue.
        void Display();                                         // Display the queue.

        T Pop();                                                // Delete the top of the queue and returns it.
        T Peek();                                               // Returns the top of the queue.

        T GetPositionValue(uint pos);                           // Returns the value found on the specified position.

        T GetMin();                                             // Returns the lowest value in the queue.
        T GetMax();                                             // Returns the highest value in the queue.

        uint Distance(T value);                                 // Returns -1 if the value isn't in the queue, else returns the distance from the top.
        uint GetSize() const { return size; }                   // Returns the number of elements found in the stack.

        bool IsEmpty() { return (first == nullptr); }           // Returns true if the queue is empty.
        bool HasValue(T value);                                 // Returns true if the value is in the queue.
        bool HasPosition(uint pos);                             // Returns true if pos is found in queue. Position 0 is top.

    private:
        struct Node
        {
            T value;
            Node *next;
        };

        Node *first, *last;
        uint size;

        Node *GetPositionAddress(uint pos);
        Node *GetValueAddress(T value);
};

template <class T>
class Deque
{
    public:

        Deque();
        ~Deque();

        void PushBack(T value);
        void PushFront(T value);

        void Display();

        T PopFront();
        T PeekFront();
        T PopEnd();
        T PeekEnd();

        T GetPositionValue(uint pos);

        T GetMin();
        T GetMax();

        uint Distance(T value);
        uint GetSize() const { return size; }

        bool IsEmpty() { return (first == nullptr); }
        bool HasValue(T value);
        bool HasPosition(uint pos);

    private:
        struct Node
        {
            T value;
            Node *next;
        };

        Node *first, *last;
        uint size;

        Node *GetPositionAddress(uint pos);
        Node *GetValueAddress(T value);
};

#include "Queue.cpp"

#endif

这是队列的使用位置。

#include "../Headers/queue.h"

// Simple linked list of queues
struct SLLQ
{
    Deque<int> deq;
    SLLQ *next;
};

void CreateStorage(SLLQ *&head, SLLQ *&tail)
{
    SLLQ *elem = new SLLQ;
    elem->next = NULL;

    if (!head)
    {
        head = elem;
        tail = elem;
    }
    else
    {
        tail->next = elem;
        tail = elem;
    }
}

int main()
{
    std::ifstream f("Inputs/hw4p7.in");

    int k, k2, n;

    Queue<int> laneIN, laneOUT;
    SLLQ *sqf = NULL, *sql = NULL;

    f >> k;
    k2 = k;
    f >> n;

    for (int i = 0; i < n; i++)
    {
        int value;
        f >> value;
        laneIN.Push(value);
    }

    k--;
    CreateStorage(sqf, sql);
    sqf->deq.PushBack(laneIN.Pop());

    // Inserting the wagons in the storage lines
    for (int i = 1; i < n; i++)
    {
        if (sqf->deq.PeekEnd() < laneIN.Peek())
            sqf->deq.PushBack(laneIN.Pop());
        else
        {
            SLLQ *temp = sqf;

            bool pushed = false;
            while (!pushed)
            {
                if (!temp->next)
                {
                    // End the program if he use to much storage lanes
                    if (!k)
                    {
                        std::cout << "There's no strategy with " << k2 << " storage lanes.";
                        _getch();
                        return;
                    }

                    k--;
                    CreateStorage(sqf, sql);
                    temp = temp->next;

                    temp->deq.PushBack(laneIN.Pop());
                    pushed = true;
                }
                else
                {
                    temp = temp->next;

                    if (temp->deq.PeekEnd() < laneIN.Peek())
                    {
                        temp->deq.PushBack(laneIN.Pop());
                        pushed = true;
                    }
                }
            }
        }
    }

    // Inserting the wagons in the out lane
    for (int i = 0; i < n; i++)
    {
        SLLQ *temp = sqf;
        Deque<int> mina = temp->deq;
        temp = temp->next;
        while (temp)
        {
            if (temp->deq.PeekFront() < mina.PeekFront())
                mina = temp->deq;
            temp = temp->next;
        }

        SLLQ *minadd = sqf;
        SLLQ *predminadd = sqf;
        while (minadd && (minadd->deq.PeekFront() != mina.PeekFront()))
        {
            minadd = minadd->next;

            if (predminadd->next != minadd)
                predminadd = predminadd->next;
        }

        laneOUT.Push(minadd->deq.PopFront());

        if (minadd->deq.IsEmpty())
        {
            delete minadd;
            predminadd->next = nullptr;
        }
    }

    laneOUT.Display();

    _getch();
    return 0;
}

这是包含队列成员定义的.cpp文件:

#include "queue.h"

template<class T>
Queue<T>::Queue()
{
    first = last = nullptr;
    size = 0;
}

template<class T>
Queue<T>::~Queue()
{
    while (first)
    {
        typename Queue<T>::Node *del = first;
        first = first->next;
        delete del;
    }
    first = last = nullptr;
    size = 0;
}

template <class T> 
void Queue<T>::Push(T value)
{
    typename Queue<T>::Node *elem = new Node;
    elem->value = value;
    elem->next = nullptr;

    if (first)
        last->next = elem;
    else
        first = elem;

    last = elem;
    size++;
}

template <class T> 
void Queue<T>::Display()
{
    typename Queue<T>::Node *temp = first;
    while (temp)
    {
        std::cout << temp->value << "\n";

        temp = temp->next;
    }
}

template <class T> 
T Queue<T>::Pop()
{
    if (IsEmpty())
        return T(-1);

    T value = first->value;

    typename Queue<T>::Node *temp = first;
    first = first->next;
    delete temp;

    if (first == nullptr)
        last = nullptr;

    size--;
    return value;
}

template <class T> 
T Queue<T>::Peek()
{
    if (IsEmpty())
        return T(-1);

    return first->value;
}

template <class T> 
T Queue<T>::GetPositionValue(uint pos)
{
    if (IsEmpty() || !HasPosition(pos))
        return T(-1);

    typename Queue<T>::Node *temp = first;
    for (uint i = 1; i < pos; i++)
        temp = temp->next;

    return temp->value;
}

template <class T> 
uint Queue<T>::Distance(T value)
{
    uint distance = 0;

    if (!HasValue(value))
        return -1;

    typename Queue<T>::Node *temp = first;
    while (temp && temp->value != value)
    {
        temp = temp->next;
        distance++;
    }

    return distance;
}

template <class T> 
T Queue<T>::GetMin()
{
    if (IsEmpty())
        return T();

    T min = first->value;

    typename Queue<T>::Node *temp = first;
    while (temp->next)
    {
        temp = temp->next;

        if (temp->value < min)
            min = temp->value;
    }

    return min;
}

template <class T> 
T Queue<T>::GetMax()
{
    if (IsEmpty())
        return T();

    T max = first->value;

    typename Queue<T>::Node *temp = first;
    while (temp->next)
    {
        temp = temp->next;

        if (temp->value > max)
            max = temp->value;
    }

    return max;
}

template <class T> 
bool Queue<T>::HasValue(T value)
{
    typename Queue<T>::Node *temp = first;
    while (temp && temp->value != value)
        temp = temp->next;

    if (!temp)
        return false;
    else
        return true;
}

template <class T> 
bool Queue<T>::HasPosition(uint pos)
{
    if (IsEmpty())
        return false;

    uint i = 1;

    typename Queue<T>::Node *temp = first;
    while (temp && i < pos)
    {
        temp = temp->next;
        i++;
    }

    if (i == pos)
        return true;
    else
        return false;
}

// Private members

template <class T> 
typename Queue<T>::Node *Queue<T>::GetPositionAddress(uint pos)
{
    if (IsEmpty() || !HasPosition(pos))
        return nullptr;

    Node *temp = first;
    for (uint i = 1; i < pos; i++)
        temp = temp->next;

    return temp;
}

template <class T> 
typename Queue<T>::Node *Queue<T>::GetValueAddress(T value)
{
    if (IsEmpty() || !HasValue(value))
        return nullptr;

    Node *temp = first;
    while (temp->value != value)
        temp = temp->next;

    return temp;
}

// Deque

template <class T>
Deque<T>::Deque()
{
    first = last = nullptr;
    size = 0;
}

template <class T>
Deque<T>::~Deque()
{
    while (first)
    {
        typename Deque<T>::Node *del = first;
        first = first->next;
        delete del;
    }
    first = last = nullptr;
    size = 0;
}

template <class T>
void Deque<T>::PushBack(T value)
{
    typename Deque<T>::Node *elem = new Node;
    elem->value = value;
    elem->next = nullptr;

    if (first)
        last->next = elem;
    else
        first = elem;

    last = elem;
    size++;
}

template <class T>
void Deque<T>::PushFront(T value)
{
    typename Deque<T>::Node *elem = new Node;
    elem->value = value;
    elem->next = nullptr;

    if (first)
        elem->next = first;
    else
        last = elem;

    first = elem;
    size++;
}

template <class T>
void Deque<T>::Display()
{
    typename Deque<T>::Node *temp = first;
    while (temp)
    {
        std::cout << temp->value << "\n";

        temp = temp->next;
    }
}

template <class T>
T Deque<T>::PopFront()
{
    if (IsEmpty())
        return T(-1);

    T value = first->value;

    typename Deque<T>::Node *temp = first;
    first = first->next;
    delete temp;

    if (first == nullptr)
        last = nullptr;

    size--;
    return value;
}

template <class T>
T Deque<T>::PeekFront()
{
    if (IsEmpty())
        return T(-1);

    return first->value;
}

template <class T>
T Deque<T>::PopEnd()
{
    if (IsEmpty())
        return T(-1);

    if (first == last)
        return PopFront();

    T value = last->value;
    typename Deque<T>::Node *temp = first;

    while (temp && temp->next != last)
        temp = temp->next;
    delete last;

    last = temp;
    size--;

    return value;
}

template <class T>
T Deque<T>::PeekEnd()
{
    if (IsEmpty())
        return T(-1);

    return last->value;
}

template <class T>
T Deque<T>::GetPositionValue(uint pos)
{
    if (IsEmpty() || !HasPosition(pos))
        return T(-1);

    typename Deque<T>::Node *temp = first;
    for (uint i = 1; i < pos; i++)
        temp = temp->next;

    return temp->value;
}

template <class T>
uint Deque<T>::Distance(T value)
{
    uint distance = 0;

    if (!HasValue(value))
        return -1;

    typename Deque<T>::Node *temp = first;
    while (temp && temp->value != value)
    {
        temp = temp->next;
        distance++;
    }

    return distance;
}

template <class T>
T Deque<T>::GetMin()
{
    if (IsEmpty())
        return T();

    T min = first->value;

    typename Deque<T>::Node *temp = first;
    while (temp->next)
    {
        temp = temp->next;

        if (temp->value < min)
            min = temp->value;
    }

    return min;
}

template <class T>
T Deque<T>::GetMax()
{
    if (IsEmpty())
        return T();

    T max = first->value;

    typename Deque<T>::Node *temp = first;
    while (temp->next)
    {
        temp = temp->next;

        if (temp->value > max)
            max = temp->value;
    }

    return max;
}

template <class T>
bool Deque<T>::HasValue(T value)
{
    typename Deque<T>::Node *temp = first;
    while (temp && temp->value != value)
        temp = temp->next;

    if (!temp)
        return false;
    else
        return true;
}

template <class T>
bool Deque<T>::HasPosition(uint pos)
{
    if (IsEmpty())
        return false;

    uint i = 1;

    typename Deque<T>::Node *temp = first;
    while (temp && i < pos)
    {
        temp = temp->next;
        i++;
    }

    if (i == pos)
        return true;
    else
        return false;
}

// Private members

template <class T>
typename Deque<T>::Node *Deque<T>::GetPositionAddress(uint pos)
{
    if (IsEmpty() || !HasPosition(pos))
        return nullptr;

    Node *temp = first;
    for (uint i = 1; i < pos; i++)
        temp = temp->next;

    return temp;
}

template <class T>
typename Deque<T>::Node *Deque<T>::GetValueAddress(T value)
{
    if (IsEmpty() || !HasValue(value))
        return nullptr;

    Node *temp = first;
    while (temp->value != value)
        temp = temp->next;

    return temp;
}

问题出在使用队列的第114行(第三行),正是:“laneOUT.Push(minadd-&gt; deq.PopFront());” 它将值放在laneOUT中,但在下一次迭代时,它会变为残值。

1 个答案:

答案 0 :(得分:1)

将近三年之后,我遇到了我的这个老问题,并想起当时我无法修复此代码,所以我想我应该尝试一下,因为我知道的更多了。

可以在主函数的第三个for循环的第二个语句中立即发现一个很大的否定:

Deque<int> mina = temp->deq;

此代码执行复制,但是Deque类虽然管理资源,但没有明确实现复制构造函数。

隐式复制构造函数将执行浅表复制,并且在for循环的第一次迭代之后,将销毁mina对象,但仍由temp-> deq指向用于初始化mina的已释放内存,第一次迭代,不知道它指向的内存已被释放。

The Rule of Three(在C ++ 11中为Five),当类管理资源时必须遵守。