首先我们用c语言定义一个栈:
stack.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST, Stack;
void StackInit(ST* ps);
void StackDestroy(ST* ps);
void StackPush(ST* ps, STDataType x);
void StackPop(ST* ps);
STDataType StackTop(ST* ps);
int StackSize(ST* ps);
bool StackEmpty(ST* ps);
stack.c
void StackInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->top = 0; // ps->top = -1;
ps->capacity = 0;
}
void StackDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
void StackPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->a = tmp;
ps->capacity = newCapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
STDataType StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->a[ps->top - 1];
}
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
bool StackEmpty(ST* ps)
{
assert(ps);
/*if (ps->top == 0)
{
return true;
}
else
{
return false;
}*/
return ps->top == 0;
}
我们用c语言实现的这个栈包括一个结构:
和它的一些函数:
C语言是一个面向过程,他的数据和方法是分离的
数据就是定义一个结构,在这个结构体里面包含各种数据:
我们指向动态开辟的数组空间,栈顶位置,容量大小
我们要操作这些数据的时候,我们要把栈对象的地址传递过去
另一方面,我们知道C++兼容这个C
第一个问题:
我们在使用这个栈的时候:
对于这种使用我们很容易忽略一些问题,也就是一些c语言的一些缺陷:
紧挨着的第一幅图片我们运行,没有任何报错,但是我们知道我们缺少了一个初始化
第二个问题:
每次传递对象我们都要取地址
每次调用任何一个函数我们都要取地址
第三个问题:
大部分人取栈顶的元素喜欢:
为什么会返回随机值
top最开始的初始值是零,插入数据需要++,所以top指向的不是最后一个数据,而是指向最后一个数据的下一个,当然也可以top最开始设为-1,插入数据之前,先++,然后再插入数据,但是我们没有用这种方式,所以避免出错,建议调用stacktop
对于C语言来说:
我们的栈实现的没有问题,但是C语言对于这些调用处理给的权限太自由,应该直接报错,这样他们就会按照规定的去调用这些函数,但是他们的调用又没有什么大的问题,只是不符合我们的栈的规定调用要求,人家的语法也是可以访问到一些不正常的结果的
基于这种问题C++是如何改变的?
1.对其进行封装,让你用你才可以用
如果你想访问栈顶的数据,你就只能访问Top 而不是_top
2.很容易忘记调用初始化和销毁
将其设为构造函数,和析构函数
3.不传地址
设置this指针