C++对象在 for 循环后获取残差值

C++ object get a residual value after a for loop

本文关键字:获取 循环 对象 for C++      更新时间:2023-10-16

我为队列创建了一个类,我在循环中使用该类的对象。迭代后,队列中第一个元素的值将更改为残差值。为什么会这样,我该如何解决?这是 .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(third for) 行,其中使用了队列,确切地说:"laneOUT.Push(minadd->deq.PopFront());"它将值放在 laneOUT 中,但在下一次迭代时它会更改为剩余值。

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

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

Deque<int> mina = temp->deq;

此代码执行复制,但 Deque 类没有显式实现复制构造函数,尽管它管理资源。

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

一个班级管理资源时,必须遵守三法则(C++11)中的五

)。