You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++类模板实现FIFO队列出队时返回3221225477错误求助

解决Queue出队时的内存崩溃问题

嘿,我来帮你排查这个问题!你遇到的3221225477错误是Windows下典型的内存访问违规,结合你的代码,主要有几个关键错误导致了这个问题,咱们一步步来修:

1. Queue类不该继承Human

你的Queue<T>模板类错误地继承了Human,这完全没必要!模板队列是通用容器,和Human类没有继承关系,这种错误继承会导致类结构混乱,尤其是当你使用非Human类型的队列时(比如你之前测试的int、float),会引发不必要的类层次问题。

修正:把继承去掉,Queue类的定义改成:

template<class T>
class Queue { // 移除public: Human的继承关系
public:
    Queue(int = 5);
    ~Queue();
    void enqueue(T);
    T dequeue();
    void PrintQueue();
private:
    T* array;
    int size, index;
};

2. Dequeue函数的两个致命错误

这是导致内存崩溃的核心原因:

(1)数组越界访问

你的dequeue循环写的是for(int i = 0; i < size; i++),当循环到i = size-1时,array[i+1]就是array[size]——而你的数组是new T[s],合法索引范围是0到size-1,访问array[size]直接触发内存越界,导致崩溃。

正确的循环应该只移动当前队列中存在的元素(也就是index个元素),只需要从第一个元素移到倒数第二个元素:

for(int i = 0; i < index - 1; i++) {
    array[i] = array[i + 1];
}

(2)函数未返回值却声明了返回类型

你的dequeue函数声明是T dequeue();,但实现里完全没有return语句,这属于未定义行为,程序会返回垃圾内存值,甚至直接崩溃。你需要返回被移除的队首元素,同时还要处理空队列的情况,避免index变成负数。

修正后的dequeue函数:

template<class T>
T Queue<T>::dequeue(){
    if(index == 0) {
        cout << "Rinda ir tukša, nevar izņemt elementu!" << endl; // 提示队列空
        // 这里可以根据需求返回默认构造的T,或者抛出异常,这里先返回默认值
        return T();
    }
    T removed = array[0]; // 保存要移除的队首元素
    for(int i = 0; i < index - 1; i++){
        array[i] = array[i + 1];
    }
    index--;
    return removed; // 返回被移除的元素
}

3. 模板类实现的规范问题

你现在在main.cpp里包含了queue.cpp,这虽然能临时解决链接问题,但不是规范写法。正确的做法是把模板类的实现放在头文件(Queue.h)里,或者在Queue.cpp末尾添加显式实例化:

// 在Queue.cpp最后添加
template class Queue<Human>;

这样就不需要在main里包含queue.cpp了。

修正后的完整代码片段

Queue.h

#ifndef QUEUE_H
#define QUEUE_H
// 模板类无需提前包含Human头文件,除非实现依赖,可在cpp中处理
template<class T>
class Queue {
public:
    Queue(int = 5);
    ~Queue();
    void enqueue(T);
    T dequeue();
    void PrintQueue();
private:
    T* array;
    int size, index;
};

// 若将实现放在cpp中,这里包含cpp;也可直接将实现写在头文件里
#include "Queue.cpp"
#endif

Queue.cpp

#include <iostream>
#include "human.h" // 在这里包含Human头文件,因为PrintQueue用到了PrintHuman方法
using namespace std;

template<class T>
Queue<T>::Queue(int s){
    array = new T[s];
    size = s;
    index = 0;
}

template<class T>
Queue<T>::~Queue(){
    delete [] array;
}

template<class T>
void Queue<T>::enqueue(T obj){
    if(index == size){
        cout << "Rinda ir pilna, nevar pievienot elementu!" << endl;
        return;
    } else {
        array[index] = obj;
        index++;
    }
}

template<class T>
T Queue<T>::dequeue(){
    if(index == 0) {
        cout << "Rinda ir tukša, nevar izņemt elementu!" << endl;
        return T();
    }
    T removed = array[0];
    for(int i = 0; i < index - 1; i++){
        array[i] = array[i + 1];
    }
    index--;
    return removed;
}

template<class T>
void Queue<T>::PrintQueue(){
    for(int i = 0; i < index; i++){
        cout << i + 1 << ". ";
        array[i].PrintHuman();
    }
}

// 显式实例化,避免main中包含cpp文件
template class Queue<Human>;

main.cpp

#include <iostream>
#include "human.h"
#include "queue.h"
using namespace std;

int main(){
    Queue<Human> HumanQueue(3);
    Human a("Janis", 1.86, 76);
    Human b("Peteris", 1.76, 69);
    Human c("Arturs", 1.79, 75);
    Human d("Aleksis", 1.81, 78);

    cout << "Elementu rinda" << endl;
    HumanQueue.enqueue(a);
    HumanQueue.enqueue(b);
    HumanQueue.PrintQueue();

    cout << "\n//Pievienojam elementu rindai//" << endl;
    HumanQueue.enqueue(c);
    HumanQueue.PrintQueue();

    cout << "\n//Meginam pievienot vel 1 elementu rindai//" << endl;
    HumanQueue.enqueue(d);
    HumanQueue.PrintQueue();

    cout << "\n//Iznemam 2 elementus no rindas//" << endl;
    HumanQueue.dequeue();
    HumanQueue.dequeue();
    HumanQueue.PrintQueue();

    system("pause");
    return 0;
}

额外建议

  • 可以给Queue类添加isEmpty()、isFull()的辅助函数,让代码更健壮。
  • 考虑用链表实现队列,避免数组移动元素的性能开销,也不会有固定大小的限制。

内容的提问来源于stack exchange,提问作者Ervīns

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 14:22:43