我发现这个类管理其数组的方式有很多问题:
-
构造函数正在分配一个int* 指针数组,但最初并未将它们中的任何一个设置为nullptr。这会导致析构函数出现问题,因为它在每个指针上调用delete,无论它们是否已被初始化。为了避免delete未使用的指针,析构函数应该循环到length,而不是maxCapacity。
-
同样,pop() 没有设置任何指向nullptr 的释放指针,这也会导致析构函数在循环到maxCapacity 而不是length 时出现问题。这也是delete'ing 错误的数组元素,如果数组达到其最大容量,则会超出范围。
-
当push() 分配一个新数组时(仅供参考,外部while 循环是不必要的),它从旧数组中复制了太多元素,而旧数组比新数组小。此外,它使用delete 而不是delete[] 来释放旧数组。
-
该类没有遵循Rule of 3/5/0,因为它应该实现(或至少禁用)复制/移动构造函数和复制/移动赋值运算符。
尝试类似的方法:
ArrayStack.h
#pragma once
#include "Stack.h"
#include "NotImplementedException.h"
class ArrayStack : public Stack
{
public:
static const int DEFAULT_CAPACITY = 10;
// ATTENTION, pour chacune des méthodes, lorsque
// vous créez sa définition dans le .cpp, vous devez
// remplacer {} (et éventuellement son contenu) par un ;
ArrayStack();
ArrayStack(const ArrayStack &src);
ArrayStack(ArrayStack &&src);
~ArrayStack();
ArrayStack& operator=(ArrayStack rhs);
void push(int element) override;
void pop() override;
int top() const override;
bool isEmpty() const override;
int size() const override;
private:
int length;
int** tab;
int topElement;
int maxCapacity;
};
ArrayStack.cpp
#include "ArrayStack.h"
#include <utility>
ArrayStack::ArrayStack()
{
maxCapacity = DEFAULT_CAPACITY;
tab = new int* [DEFAULT_CAPACITY];
for (int i = 0; i < DEFAULT_CAPACITY; ++i) {
tab[i] = nullptr;
}
length = 0;
topElement = -1;
}
ArrayStack::ArrayStack(const ArrayStack &src)
{
maxCapacity = src.maxCapacity;
tab = new int* [maxCapacity];
for (int i = 0; i < src.length; ++i) {
tab[i] = new int (*(src.tab[i]));
}
for (int i = src.length; i < maxCapacity; ++i) {
tab[i] = nullptr;
}
length = src.length;
topElement = src.topElement;
}
ArrayStack::ArrayStack(ArrayStack &&src)
{
maxCapacity = src.maxCapacity; src.maxCapacity = 0;
tab = src.tab; src.tab = nullptr;
length = src.length; src.length = 0;
topElement = src.topElement; src.topElement = -1;
}
ArrayStack& ArrayStack::operator=(ArrayStack rhs)
{
std::swap(maxCapacity, rhs.maxCapacity);
std::swap(tab, rhs.tab);
std::swap(length, rhs.length);
std::swap(topElement, rhs.topElement);
return *this;
}
ArrayStack::~ArrayStack()
{
for (int i = 0; i < length; ++i) {
delete tab[i];
}
delete[] tab;
}
void ArrayStack::push(int element)
{
if (maxCapacity <= length) {
int newCapacity = maxCapacity + DEFAULT_CAPACITY;
int** temp = new int* [newCapacity];
for (int i = 0; i < length; ++i) {
temp[i] = tab[i];
}
for (int i = length; i < newCapacity; ++i) {
temp[i] = nullptr;
}
delete[] tab;
tab = temp;
maxCapacity = newCapacity;
}
tab[length] = new int (element);
++length;
topElement = element;
}
void ArrayStack::pop()
{
if (isEmpty()) {
throw Empty_Stack();
}
--length;
delete tab[length];
tab[length] = nullptr;
if (isEmpty()) {
topElement = -1;
}
else {
topElement = *tab[length-1];
}
}
int ArrayStack::top() const
{
if (isEmpty()) {
throw Empty_Stack();
}
return topElement;
}
bool ArrayStack::isEmpty() const
{
return (length == 0);
}
int ArrayStack::size() const
{
return length;
}
Online Demo
话虽如此,完全没有充分的理由使用int* 指针数组。您应该改用 int 值的数组。这样你手动管理的东西就会少一点:
ArrayStack.h
#pragma once
#include "Stack.h"
#include "NotImplementedException.h"
class ArrayStack : public Stack
{
public:
static const int DEFAULT_CAPACITY = 10;
// ATTENTION, pour chacune des méthodes, lorsque
// vous créez sa définition dans le .cpp, vous devez
// remplacer {} (et éventuellement son contenu) par un ;
ArrayStack();
ArrayStack(const ArrayStack &src);
ArrayStack(ArrayStack &&src);
~ArrayStack();
ArrayStack& operator=(ArrayStack rhs);
void push(int element) override;
void pop() override;
int top() const override;
bool isEmpty() const override;
int size() const override;
private:
int length;
int* tab;
int topElement;
int maxCapacity;
};
ArrayStack.cpp
#include "ArrayStack.h"
#include <utility>
ArrayStack::ArrayStack()
{
maxCapacity = DEFAULT_CAPACITY;
tab = new int [DEFAULT_CAPACITY];
length = 0;
topElement = -1;
}
ArrayStack::ArrayStack(const ArrayStack &src)
{
maxCapacity = src.maxCapacity;
tab = new int [maxCapacity];
for (int i = 0; i < src.length; ++i) {
tab[i] = src.tab[i];
}
length = src.length;
topElement = src.topElement;
}
ArrayStack::ArrayStack(ArrayStack &&src)
{
maxCapacity = src.maxCapacity; src.maxCapacity = 0;
tab = src.tab; src.tab = nullptr;
length = src.length; src.length = 0;
topElement = src.topElement; src.topElement = -1;
}
ArrayStack& ArrayStack::operator=(ArrayStack rhs)
{
std::swap(maxCapacity, rhs.maxCapacity);
std::swap(tab, rhs.tab);
std::swap(length, rhs.length);
std::swap(topElement, rhs.topElement);
return *this;
}
ArrayStack::~ArrayStack()
{
delete[] tab;
}
void ArrayStack::push(int element)
{
if (maxCapacity <= length) {
int newCapacity = maxCapacity + DEFAULT_CAPACITY;
int* temp = new int [newCapacity];
for (int i = 0; i < length; ++i) {
temp[i] = tab[i];
}
delete[] tab;
tab = temp;
maxCapacity = newCapacity;
}
tab[length] = element;
++length;
topElement = element;
}
void ArrayStack::pop()
{
if (isEmpty()) {
throw Empty_Stack();
}
--length;
if (isEmpty()) {
topElement = -1;
}
else {
topElement = tab[length-1];
}
}
int ArrayStack::top() const
{
if (isEmpty()) {
throw Empty_Stack();
}
return topElement;
}
bool ArrayStack::isEmpty() const
{
return (length == 0);
}
int ArrayStack::size() const
{
return length;
}
Online Demo
在这种情况下,更好的选择是用 std::vector 替换手动数组,让它为您完成所有繁重的工作:
ArrayStack.h
#pragma once
#include "Stack.h"
#include "NotImplementedException.h"
#include <vector>
class ArrayStack : public Stack
{
public:
static const int DEFAULT_CAPACITY = 10;
// ATTENTION, pour chacune des méthodes, lorsque
// vous créez sa définition dans le .cpp, vous devez
// remplacer {} (et éventuellement son contenu) par un ;
ArrayStack();
void push(int element) override;
void pop() override;
int top() const override;
bool isEmpty() const override;
int size() const override;
private:
std::vector<int> tab;
int topElement;
};
ArrayStack.cpp
#include "ArrayStack.h"
ArrayStack::ArrayStack()
{
tab.reserve(DEFAULT_CAPACITY);
topElement = -1;
}
void ArrayStack::push(int element)
{
tab.push_back(element);
topElement = element;
}
void ArrayStack::pop()
{
if (isEmpty()) {
throw Empty_Stack();
}
tab.pop_back();
if (tab.empty()) {
topElement = -1;
}
else {
topElement = tab.back();
}
}
int ArrayStack::top() const
{
if (isEmpty()) {
throw Empty_Stack();
}
return topElement;
}
bool ArrayStack::isEmpty() const
{
return tab.empty();
}
int ArrayStack::size() const
{
return tab.size();
}
Online Demo
然后,最后,改用std::stack:
ArrayStack.h
#pragma once
#include "Stack.h"
#include "NotImplementedException.h"
#include <stack>
class ArrayStack : public Stack
{
public:
// ATTENTION, pour chacune des méthodes, lorsque
// vous créez sa définition dans le .cpp, vous devez
// remplacer {} (et éventuellement son contenu) par un ;
void push(int element) override;
void pop() override;
int top() const override;
bool isEmpty() const override;
int size() const override;
private:
std::stack<int> tab;
};
ArrayStack.cpp
#include "ArrayStack.h"
void ArrayStack::push(int element)
{
tab.push(element);
}
void ArrayStack::pop()
{
if (isEmpty()) {
throw Empty_Stack();
}
tab.pop();
}
int ArrayStack::top() const
{
if (isEmpty()) {
throw Empty_Stack();
}
return tab.top();
}
bool ArrayStack::isEmpty() const
{
return tab.empty();
}
int ArrayStack::size() const
{
return tab.size();
}
Online Demo
看看清洁度有多高? :-)