C++类模板实现FIFO队列出队时返回3221225477错误求助
嘿,我来帮你排查这个问题!你遇到的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

