c++ - 析构函数数组堆栈tiwer hanoi c++双指针
问题描述
我尝试将元素推入堆栈,但它表明存在空间量错误。如果长度大于容量,容量会升级。有人知道如何纠正这个错误吗?我认为这可能来自析构函数,但我对此不太确定。
ArrayStack.cpp
#include "ArrayStack.h"
ArrayStack::ArrayStack()
{
maxCapacity = DEFAULT_CAPACITY;
this->tab = new int* [DEFAULT_CAPACITY];
this->topElement = 0;
this->length = 0;
}
ArrayStack::~ArrayStack()
{
for (int i = 0; i < maxCapacity; i++)
{
delete tab[i];
}
delete[] tab;
}
void ArrayStack::push(int element)
{
this->length++;
while (this->maxCapacity <= this->length) {
maxCapacity += DEFAULT_CAPACITY;
int** temp = new int* [maxCapacity];
for (int i = 0; i < maxCapacity; i++)
{
temp[i] = tab[i];
}
delete tab;
this->tab = temp;
}
this->tab[this->length] = new int (element);
this->topElement = element;
}
void ArrayStack::pop()
{
if (isEmpty())
{
throw Empty_Stack();
}
delete tab[this->length];
this->length--;
if (isEmpty())
{
this->topElement = -1;
}
else
{
this->topElement = *tab[this->length];
}
}
int ArrayStack::top() const
{
if (isEmpty())
{
throw Empty_Stack();
}
return this->topElement;
}
bool ArrayStack::isEmpty() const
{
if (this->length == 0)
{
return true;
}
return false;
}
int ArrayStack::size() const
{
return this->length;
}
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();
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;
};
解决方案
我发现此类管理其数组的方式存在许多问题:
构造函数正在分配一个指针数组
int*
,但没有将它们中的任何一个设置为nullptr
初始值。这会导致析构函数出现问题,因为它正在调用delete
每个指针,无论它们是否已初始化。为了避免不得不delete
使用未使用的指针,析构函数应该循环到length
,而不是maxCapacity
。同样,
pop()
没有将任何已释放的指针设置为nullptr
,这也会导致析构函数在循环到maxCapacity
而不是时出现问题length
。它也是delete
错误的数组元素,如果数组达到其最大容量,则会超出范围。当
push()
分配一个新数组时(仅供参考,外部while
循环是不必要的),它从旧数组中复制了太多元素,这比新数组小。此外,它使用delete
而不是delete[]
释放旧数组。该类不遵循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;
}
话虽如此,根本没有充分的理由使用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;
}
在这种情况下,更好的选择是替换手动数组,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();
}
然后,最后,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();
}
看看清洁度有多高?:-)
推荐阅读
- php - 获取类别中显示的所有产品的 WooCommerce 产品条款
- php - Phalcon PHP 单元测试 DI 共享实例
- java - 如何在 Java 中使用 JAXB 将 XML 字符串解组到列表
- google-apps-script - 如何使用 Google Apps 脚本编辑 Google 照片中的多张照片?
- timestamp - 从 Notepad++ 中的字幕文件中删除空行和时间戳
- android - Android /获取与被解雇的通知相对应的ID
- dart - 我尝试创建 facebook 登录。如何解决这个问题?
- c# - 我们能否在具有共享托管的 Linux 服务器上托管一个自包含的 ASP.NET Core 应用程序
- extjs - 表单字段值在提交过程中转义,除非表单字段值禁用选项
- android - 从 fragD 到 fragA 的 popBackStack 之后调用了哪个方法?