我正在编写一个程序来实现一个像真实世界堆栈一样工作的堆栈,这意味着它在堆栈大小达到阈值时会倒塌,因此需要创建一个新堆栈来插入新元素。
以下是我的计划:
#include <iostream>
#include<vector>
#include<stack>
using namespace std;
class stack_of_plates
{
vector<stack<int> > stacks;
unsigned int stack_size;
public:
stack_of_plates(unsigned int size=100)
{
stack_size=size;
}
void push(int data)
{
if(stacks.empty())
{
stack<int> *sptr= new stack<int>; //on debugging Segmentation fault at thisline
stacks.push_back(*sptr);
}
vector<stack<int> >::iterator it=stacks.end();
if(it->size()==stack_size)
{
stack<int> *sptr= new stack<int>; //on debugging Segmentation fault at thisline
stacks.push_back(*sptr);
}
it->push(data);
}
void pop()
{
if(stacks.empty())
{
cout<<"\nEmpty Stack";
return ;
}
vector<stack<int> >::iterator it=stacks.end();
if(it->empty())
{
it--;
}
it->pop();
}
int top()
{
if(stacks.empty())
{
cout<<"\nEmpty Stack";
return 0;
}
vector<stack<int> >::iterator it=stacks.end();
if(it->empty())
{
it--;
}
return it->top();
}
};
int main()
{
stack_of_plates ss;
ss.push(1);
ss.push(2);
cout<<ss.top();
return 0;
}
编译时不会出现错误或警告。但程序终止时会出现异常错误。 在调试其给出分段错误错误时指示分配新堆栈的问题。 请帮助我如何在分配新堆栈时更改我的代码。请帮我删除此错误。
答案 0 :(得分:3)
stacks.end();
是指向量结束后的(不存在的)元素。你不能取消引用它;这样做会导致未定义的行为,可能是分段错误。
你在那里做什么并不是很清楚,但是如果你想要最后一个元素的迭代器,那么要么减少它:
vector<stack<int> >::iterator it=stacks.end(); // points past the end
--it; // points to last element
或使用反向迭代器(在这种情况下,使用++
而不是--
向后移动序列):
vector<stack<int> >::reverse_iterator it=stacks.rbegin();
向向量添加元素可能会使其无效,因此it->push_back(data)
末尾的push()
不正确。你可以避免在这里使用迭代器:
void push() {
if (stacks.empty() || stacks.back().size()==stack_size) {
// See below for explanation of this change
stacks.push_back(stack<int>());
}
stacks.back().push(data);
}
在pop()
中,你可能想删除最后一个堆栈,如果它是空的;否则,你最终会得到两个空堆栈,而你的代码将错误地尝试其中一个pop
。同样,这样做可能会导致分段错误或其他未定义的行为。你可能想要这样的东西:
void pop() {
if (stacks.empty()) {
cout<<"\nEmpty Stack";
return ;
}
stacks.back().pop();
if (stacks.back().empty()) {
stacks.pop_back();
}
}
现在我们已经建立了一个不变量,即最后一个堆栈永远不会为空,top
可以更简单一些:
int top() {
if (stacks.empty()) {
cout<<"\nEmpty Stack";
return 0;
}
return stacks.back().top();
}
此外,您通常不希望使用new
创建对象,尤其是在这样的情况下,您将对象的副本放入向量,然后丢弃指针,泄漏分配的内存。您可以向向量添加一个空堆栈,如下所示:
stacks.push_back(stack<int>());
有时(但不是在这种情况下)您可能希望存储指向容器中已分配对象的指针;在这种情况下,要么记得在从容器中删除它们时删除它们,要么存储智能指针,例如std::unique_ptr
。但在这种情况下,只需存储对象。
答案 1 :(得分:1)
代码存在许多问题,因此很难说哪一个是导致问题的直接原因。您需要逐个清理它们然后重新测试。如果您仍有问题,请在此处发布新代码。
以下是清单:
您的分配中存在内存泄漏问题。由于你有一个堆栈向量,你需要做的就是调整向量的大小,并分配一个新的堆栈。所以
stacks.resize(stacks.size() + 1)
;
而不是
stack<int> *sptr= new stack<int>
;
stacks.push_back(*sptr)
;
vector&lt;&gt; .end()返回一个指向最后一个元素的迭代器,这就是为什么@Joachim建议你在使用它之前需要递减迭代器的原因。
< / LI>检查是否将存储转移到新堆栈时出现逻辑错误 - 检查最后一个堆栈的大小是否为最大值,然后创建新堆栈,继续推送旧堆栈。
我希望这会有所帮助。
答案 2 :(得分:0)
std::stack<int>
已经具有您在示例中显示的功能,因此不需要std::vector< std::stack<int> >
。只需按下并弹出std::stack<int>
即可避免代码中出现的大部分问题。没有理由将std::stack<int>
限制为stack_size
。
接下来,当您需要容器中的最后一个条目时,请使用back()
代替end()
。