#c #arrays #stack
#c #массивы #стек
Вопрос:
Моя проблема в том, что моя функция удаления не работает.Когда я помещаю элемент в стек, затем отображаю его, и после этого, если я удалю весь стек, поэтому, когда я его отобразил, он должен выводить значения мусора, но это не тот случай, когда он снова показывает те же значения, как если бы ничего не удалялось.
#include<iostream.h>
#include<conio.h>
template<class T>
class stack
{
int capacity;
public:
T *array;
int top;
stack(int);
void push(T);
T pop();
int stackempty();
int stackfull();
void display();
void deletestack();
};
template<class T>
stack<T>::stack(int max)
{
top=-1;
capacity=max;
array=new T[capacity];
}
template<class T>
void stack<T>::push(T data)
{
if(stackfull())
cout<<"stack overflow";
else
array[ top]=data;
}
template<class T>
T stack<T>::pop()
{
if(stackempty())
{
cout<<"stack underflow";
return -1;
}
else
return array[top--];
}
template<class T>
int stack<T>::stackempty()
{
if(top==-1)
return 1;
else
return 0;
}
template<class T>
int stack<T>::stackfull()
{
if(top==capacity-1)
return 1;
else
return 0;
}
template<class T>
void stack<T>::display()
{
int i;
if(top==-1)
cout<<"empty stack";
else
for(i=0;i<=top;i )
cout<<"n"<<array[i];
}
template<class T>
void stack<T>::deletestack()
{
delete []array;
}
int main()
{
stack<int>* S=new stack<int>(20);
clrscr();
S->push(5);
S->push(10);
S->push(15);
S->display();
S->deletestack();
S->display();
S->push(5);
S->display();
getch();
return 0;
}
Комментарии:
1. Если вы хотите очистить свой стек, тогда сделайте
top = -1;
вместоdelete[] array;
. То, как вы спроектировали свой стек, заключается в том, что предполагается, что в нем всегда должныcapacity
быть выделены элементы, иtop
указывается, сколько из этих элементов «используется».
Ответ №1:
Это намного больше кода, чем необходимо для иллюстрации этой проблемы, но в любом случае… Если вы delete[]
используете массив, повторный доступ к нему является неопределенным поведением. При повторном доступе к нему ваша программа может вообще что-либо делать.
Это включает в себя отображение значений, которые уже были в этой памяти. Это мусор. Они просто оказываются мусором, который очень похож на значения, которые вы уже указали здесь. Причина, по которой это происходит, заключается в том, что было бы дополнительной работой пройти и заполнить эту память, скажем, нулями. Вам больше не разрешено смотреть на него, так что кого волнует, что там.
Комментарии:
1. @nightshade Нет! Это определенно не разрешено
c
(или эквивалентноc
сmalloc
помощью /free
). Компилятор превратит его во что-то, что будет выполняться, и код будет выглядетьc
, но он больше не является (действительным)c
.2. это не то, что означает запретить… его программа не зависала, когда он пытался получить доступ… предоставление неопределенного поведения — это не то же самое, что «не разрешить»… Я думаю, что это неопределенное поведение должно быть вместо сбоев (очень помогло бы в отладке)
3. Почему это должно произойти сбой? Вы нарушили контракт. Вы проиграли. И на техническом уровне, почему это должно произойти сбой? Вы обращаетесь к памяти в адресном пространстве вашей программы. Если это произошло с ошибкой, это потому, что вы сделали что-то, запрещенное операционной системой , а не языком .
Ответ №2:
Представьте, что у вас есть несколько домов в колонии. Теперь они вам не принадлежат. Это не означает, что эти дома разрушены. Может случиться так, что дома есть как есть. Может случиться, что там нет дома.
Аналогично, память, выделенная для вашего массива, все еще существует, и у вас есть его адрес. Может случиться так, что местоположение имеет те же данные или нет.
Ответ №3:
Строка delete []array;
в вашем методе deletestack() освободит массив памяти, на который указывает вызываемый указатель array
. (однако free — это не то же самое, что записать поверх него что-то другое)
После вызова delete вы возвращаете память операционной системе, доступ к ней после ее возврата в операционную систему является неопределенным поведением. Иногда это приведет к ошибке сегментации и сбою, а иногда ничего плохого не произойдет. C в этом отношении сильно отличается от таких языков, как Java, которые активно ищут незаконный доступ к памяти и немедленно выдают исключение. В C ожидается, что программист будет следовать правилам, и никто не проверяет его.
В любом случае освобождение памяти не означает, что она очищена. Старые значения, которые вы туда поместили, все еще существуют до тех пор, пока что-то другое не выделит эту память и не начнет записывать в нее.
В опубликованном вами коде есть много других проблем, которые могут вызвать странное поведение, если он используется:
stack<int>* S=new stack<int>(20);
выделил объект в куче, который никогда не удаляется. stack
выделяет массив во время построения, однако dtor не освобождает массив. Пользователь, который забывает позвонить deletestack
, приведет к утечке памяти stack
содержит ссылку на выделенный массив, однако у него нет copy-ctor или operator=, и он их не удаляет.