在堆栈类中使用指针

Use of pointers in a stack class?

本文关键字:指针 堆栈      更新时间:2023-10-16

我正在学习c++,我们做了一个使用类模板和指针创建堆栈类的练习。我还没有完全理解堆栈或指针的实现所以我试着写了这个类:

template <class T>
class Stack_Class {
public:
    T* stack;
    int item_quantity;
    T* First_item;
    int Max_quantity;
    Stack_Class(int value);
    ~Stack_Class();
    bool Add(T value);
    T Pop();
    int GetMax_Quantity();
    bool Full();
    bool Empty();
};

template <class T>
Stack_Class<T>::Stack_Class(int value) {
    if (value > 0) {
        stack = new T[value];
        First_item = stack;
        item_quantity = 0;
        Max_quantity = value;
    }
}
template <class T>
Stack_Class<T>::~Stack_Class() {
    if (First_item) {
        delete First_item;
    }
}

template<class T>
bool Stack_Class<T>::Add(T num) {
    if (item_quantity <Max_quantity) {
        *stack = num;
        stack++;
        item_quantity++;
        return true;
    }
    else return false;
}
template<class T>
T Stack_Class<T>::Pop() {
    if (!Empty()) {
        item_quantity--;
        return stack[item_quantity];
    }
     return NULL;
}
template<class T>
bool Stack_Class<T>::Empty() {
    return (item_quantity == 0);
}
template <class T>
int Stack_Class<T>::GetMax_Quantity() {
    return Max_quantity;
}

主类是:

#include <iostream>
#include "Stack_Class.h"
void main() {
    Stack_Class<int> intStack(3);
    intStack.Add(1);
    intStack.Add(2);
    intStack.Add(3);
    int count = intStack.GetMax_Quantity();
    for (int i = 0; i < count; i++) {
        std::cout << "Pop No: " << i << " - Elemento: "  << intStack.Pop() << std::endl;
    }
}

虽然作为结果,我得到的所有随机数,而不是那些我给它在intStack。我的问题是,我是否正确地实现了指针?

您需要在Pop()中引用stack指针之前减少它的增量:

template<class T>
T Stack_Class<T>::Pop(){
    if (!Empty()){
        item_quantity--;
        stack--;
        return *stack;
    }
    return NULL;
}

你的数组访问stack[item_quantity]不工作,因为你增加Add中的stack。所以在构造之后,stack指向的内存看起来像这样

0xff65f96f  <-- *(stack + 0)
0x0eec604f  <-- *(stack + 1)
0x05be0582  <-- *(stack + 2)
0x29b9186e  <-- *(stack + 3)

十六进制值表示分配时恰好位于内存中的随机垃圾。这是因为new分配的内存没有被初始化为好的内存。添加三个值后,它看起来像这样

1           <-- *(stack - 3)
2           <-- *(stack - 2)
3           <-- *(stack - 1)
0x29b9186e  <-- *(stack + 0)
0xf66eff06  <-- *(stack + 1)
0x357eb508  <-- *(stack + 2)

Pop的第一次调用中,您访问stack[2] = *(stack + 2),因为item_quantity在自减之后是2。连续两次呼叫Pop访问stack[1]stack[0]。正如你在上面看到的,你从来没有真正引用过你放到堆栈中的值。

您混淆了Add方法中的指针递增语义和Pop方法中的索引语义。

由于您需要Empty方法的索引等,我将修复您的Add方法而不是Pop,如下所示。

否则,您最终会在某些方法中使用索引,而在其他方法中不使用索引。在我看来,这是不一致的。

template<class T>
bool Stack_Class<T>::Add(T num){
    if (item_quantity <Max_quantity){       
        stack[item_quantity++] = num;
        return true;
    }
    else return false;
}
你代码中的另一个问题是:
stack = new T[value];

但是你似乎只删除了指针中的第一个元素。这是一个保证的(并且可能不可忽略的)内存泄漏。

即使你修复了所有这些,你的代码仍然无法编译,因为你试图返回void,而c++程序应该返回int,所以改变这个:

void main(){
    ...
}

:

int main(){
    ...
}

…并返回一个类似于0的整数。

你还需要修复这个警告:

Stack_Class.h:56:13: warning:从NULL转换为非指针类型' int ' [-Wconversion-null]返回NULL;^

修复了所有这些,输出如下所示:

Pop No: 0 - Elemento: 3
Pop No: 1 - Elemento: 2
Pop No: 2 - Elemento: 1

您还可以看到在ideone上运行的代码。

为方便起见,以下是修复后的全部工作代码:

template <class T>
class Stack_Class{
public:
    T* stack;
    int item_quantity;
    T* First_item;
    int Max_quantity;
    Stack_Class(int value); 
    ~Stack_Class();
    bool Add(T value);
    T Pop();
    int GetMax_Quantity();
    bool Full();
    bool Empty();   
};

template <class T>
Stack_Class<T>::Stack_Class(int value){
    if (value > 0){
        stack = new T[value];
        First_item = stack;
        item_quantity = 0;
        Max_quantity = value;
    }
}
template <class T>
Stack_Class<T>::~Stack_Class(){
    if (First_item){
        delete First_item;
    }
}

template<class T>
bool Stack_Class<T>::Add(T num){
    if (item_quantity <Max_quantity){       
        *stack = num;
        stack++;
        item_quantity++;
        return true;
    }
    else return false;
}
template<class T>
T Stack_Class<T>::Pop(){
    if (!Empty()){
        item_quantity--;
        return stack[item_quantity];
    }
     return NULL;
}
template<class T>
bool Stack_Class<T>::Empty(){
    return (item_quantity == 0);
}
template <class T>
int Stack_Class<T>::GetMax_Quantity(){
    return Max_quantity;
}