我自己的堆栈类中的 C++ 奇怪行为
Posted
技术标签:
【中文标题】我自己的堆栈类中的 C++ 奇怪行为【英文标题】:C++ Strange behavior in my own stack class 【发布时间】:2015-03-28 12:06:44 【问题描述】:这是一个包含我的 Stack 类和其他一些函数的程序。
ReadTheFile()
- 读取存储在num_file.txt
中的数字,并返回包含这些数字的向量。
IntervalCheck()
- 从输入向量中添加特定范围的数字并返回仅包含这些数字的向量。
VecToMyStack()
- 将数字从向量添加到堆栈。
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#define STACK_EMPTY -1
#define OUT_OF_STACK -2
using namespace std;
template <class T>
class Stack
private:
struct Node
T element;
Node *prevElement;
;
size_t NumberOfElements;
Node *tempAdr;
Node *topElement;
Node *newElement;
Node *erasedElement;
public:
Stack()
topElement = new Node;
topElement->prevElement = nullptr;
NumberOfElements = 0;
~Stack()
cout << endl << "I'm a destructor";
while(NumberOfElements !=0 )
tempAdr = topElement->prevElement;
delete topElement;
topElement = tempAdr;
NumberOfElements--;
delete topElement;
void push(T input_element)
tempAdr = topElement;
topElement = new Node;
topElement->element = input_element;
topElement->prevElement = tempAdr;
NumberOfElements++;
void pop()
if (NumberOfElements == 0) throw STACK_EMPTY;
else
tempAdr = topElement->prevElement;
delete topElement;
topElement = tempAdr;
NumberOfElements--;
T top()
return NumberOfElements != 0 ? topElement->element : throw STACK_EMPTY;
void insert(size_t position, T input_element)
if (position >= NumberOfElements) throw OUT_OF_STACK;
else
tempAdr = topElement;
for (size_t i = 0; i < position; i++)
tempAdr = tempAdr->prevElement;
newElement = new Node;
newElement->element = input_element;
newElement->prevElement = tempAdr->prevElement;
tempAdr->prevElement = newElement;
NumberOfElements++;
void erase(size_t position)
if (position >= (NumberOfElements-1)) throw OUT_OF_STACK;
else
tempAdr = topElement;
for (size_t i = 0; i < position; i++)
tempAdr = tempAdr->prevElement;
erasedElement = tempAdr->prevElement;
tempAdr->prevElement = tempAdr->prevElement->prevElement;
delete erasedElement;
NumberOfElements--;
void print()
if (NumberOfElements != 0)
tempAdr = topElement;
for (size_t i = 0; i < NumberOfElements; i++)
cout << tempAdr->element << " ";
tempAdr = tempAdr->prevElement;
size_t size() return NumberOfElements;
;
vector<int> ReadTheFile()
vector<int> vec_from_file;
int buffer;
ifstream basefile;
basefile.open("num_file.txt", ios::in);
if (basefile.is_open())
do
if (basefile >> buffer)
vec_from_file.push_back(buffer);
else
basefile.clear();
basefile.ignore(1, ' ');
while (!basefile.eof());
basefile.close();
else cout << "Unable to open file" << endl;
return vec_from_file;
vector<int> IntervalCheck(vector<int> vec_for_check)
vector<int> out_vec;
if (vec_for_check.empty()) cout << "There is nothing to check";
else
int begin_int, end_int;
do
cin.clear();
cin.sync();
cout << "Input the first and the last value of the interval: ";
cin >> begin_int >> end_int;
while (cin.fail());
for (auto &k : vec_for_check)
if (k > begin_int && k < end_int)
out_vec.push_back(k);
return out_vec;
Stack<int> VecToMyStack(vector<int> input_vec)
Stack<int> output_st;
if (input_vec.empty())
cout << "the end";
else
for (auto &k : input_vec)
output_st.push(k);
return output_st;
int main()
int choice = 0;
do
cin.clear();
cin.sync();
VecToMyStack(IntervalCheck(ReadTheFile())).print();
cout << "Would you like to measure another interval? 1-yes 2-no";
cin >> choice;
while (choice == 1);
system("pause");
return 0;
整个程序应该将文件中的数字压入堆栈,并使用类的print()
方法打印该堆栈。例如,如果有一个 num_file.txt
和
0 1 2 3 4 5 6 7 8 9 10
在里面,程序应该是这样工作的:
输入区间的第一个和最后一个值:0 10 /* 零和 十个由用户输入*/ 1 2 3 4 5 6 7 8 9 您想测量另一个区间吗? 1-是 2-否但是当VecToMyStack(IntervalCheck(ReadTheFile())).print();
行被执行时,我得到了
访问冲突读取位置 0xFEEEFEEE。
异常。我的 Stack 类的析构函数似乎在 print()
function 之前运行。为什么会这样?我应该在 Stack 类或 VecToMyStack()
函数中添加什么特别的东西吗?
【问题讨论】:
0xFEEEFEEE
是MSVC debug heap implementation 中的一个特殊值。删除后你正在使用的东西。
你真的需要了解一下the rule of three。
可能是错字。循环中的删除是delete topElement;
,但应该是delete tempAdr;
您的stack
类存在根本缺陷,在您实现用户定义的复制构造函数和赋值运算符之前无法正常工作。您正在按值返回 Stack
,这无法与您拥有的代码一起正常工作。 (就好像没有人被教过 3 法则,只有到了这里或其他网站才意识到。教 C++ 的状态有这么糟糕吗?)
好吧伙计们,看来我应该遵循三原则
【参考方案1】:
最后,经过几个小时的研究,我终于找到了缺失的代码:
Stack(const Stack &object)
tempAdr = object.topElement;
T * tempMas=new T[object.NumberOfElements];
for (size_t i = 0; i < object.NumberOfElements; i++)
tempMas[i] = tempAdr->element;
tempAdr = tempAdr->prevElement;
topElement = new Node;
topElement->prevElement = nullptr;
NumberOfElements = 0;
for (int i = object.NumberOfElements - 1; i >= 0; i--)
push(tempMas[i]);
delete[] tempMas;
我知道如果没有重载的赋值运算符,我的 Stack 类仍然不完整,但至少我的代码运行良好。
【讨论】:
以上是关于我自己的堆栈类中的 C++ 奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章
在子类中定义一个属性,然后在父类中使用它,PHP中的奇怪行为?
c++如何直接调用自己写的类中的函数,就像调用标准库中的函数那样