调用 delete[] 会破坏我的 C++ 程序
Calling delete[] breaks my C++ program
更新:感谢您的快速回复。看来我发布了旧版本的代码。除了参数化构造函数之外,一切都保持不变。如您所见,代码中存在一些缺陷,但请记住,我还没有完全完成这个。目前我更担心数组,因为这是昨天介绍的新概念。
我尝试了几种不同的方法并研究了几个小时。大多数回复说只使用向量 class 但这是为了帮助我们理解内存分配和动态数组的家庭作业。目前这是给我带来问题的 .cpp 和 .h 文件。每次触发删除(或清除函数)操作时,都会发生错误,指出 blahblah.exe 已触发断点。
MyVector.h
#pragma once
class MyVector
{
private:
int arraySize;
int arrayCapacity;
int* theData;
void grow();
public:
MyVector();
MyVector(int n);
int size() const;
int capacity() const;
void clear();
void push_back(int n);
int& at(int n);
~MyVector();
};
MyVector.cpp
#include "MyVector.h"
#include <iostream>
using namespace std;
MyVector::MyVector()
{
arraySize = 0;
arrayCapacity = 0;
theData = new int[0];
}
MyVector::MyVector(int capacityIn)
{
theData = new int [capacityIn];
arraySize = 0;
arrayCapacity = 0;
}
int MyVector::size() const
{
return arraySize;
}
int MyVector::capacity() const
{
return arrayCapacity;
}
void MyVector::clear()
{
delete [] theData;
theData = nullptr;
}
void MyVector::push_back(int n)
{
if (arrayCapacity==0)
{
arrayCapacity++;
MyVector(arrayCapacity);
}
if (arraySize == arrayCapacity)
{
grow();
MyVector(arrayCapacity);
}
theData[arraySize] = n;
arraySize++;
}
int& MyVector::at(int index)
{
if (index >= 0 && index<arraySize)
{
return (theData[index]);
}
else
{
throw index;
}
}
void MyVector::grow()
{
arrayCapacity = arrayCapacity + arrayCapacity;
}
MyVector::~MyVector()
{
if (theData != nullptr)
{
clear();
}
}
这里:
MyVector::MyVector(int capacityIn)
{
int* theData = new int [capacityIn];
}
您声明了一个局部指针 theData
,它隐藏了当前对象的 theData
数据成员,使其未初始化。从那里开始,所有关于使用它的赌注都被取消了,它是你的程序最终崩溃的 delete[]
纯属偶然。写入
MyVector::MyVector(int capacityIn)
{
theData = new int [capacityIn];
}
相反,arraySize
和 arrayCapacity
也必须初始化。
除此之外,您将运行遇到
的问题
MyVector(arrayCapacity);
在 push_back
函数中分配了一个 MyVector
类型的临时对象,该对象(几乎)立即再次被销毁;它不会更改当前对象。
你有很多问题我已经看到了:
- 您不应该像这样显式调用构造函数。它不会按照你的想法去做。将分配放在真正的成员函数中。
- 每次你 "grow" 你的数组,你只是分配新的,导致泄漏,因为以前的指针没有被删除。
- 您要问的主要问题:您甚至没有存储在构造函数中分配的指针。将
int* theData = new int [capacityIn];
更改为 theData = new int [capacityIn];
。例如,您在第一个构造函数中做得正确。
- 您没有在第二个构造函数 (
MyVector(int)
) 中初始化 arraySize
或 arrayCapacity
。
吹毛求疵:
- 删除前无需检查
nullptr
。
- 没必要
new int[0]
。您永远不应该访问内存,因此只需将其初始化为 nullptr
.
这导致您无法解决问题:
int* theData = new int [capacityIn];
你说的是:"Please define an integer pointer..."等等。成员变量不同于您在方法中定义的变量;这样做是没有意义的。相反,你应该这样做:
theData = new int [capacityIn];
或者,仅出于教育目的(并且为了让您理解我们正在分配给成员变量):
this->theData = new int [capacityIn];
另外(有些点可能不是那么重要,但因为你是新人,我想指出一下):
请在第二个构造函数中设置您的其他变量,您似乎忘记这样做了。
MyVector::MyVector(int capacityIn)
{
theData = new int [capacityIn];
arraySize = capacityIn;
arrayCapacity = capacityIn;
}
你应该有有意义的名字,theData
是你绝对应该避免的。 http://petdance.com/2012/04/the-worlds-two-worst-variable-names/
- 您的方法应以动词开头,例如
getDimension()
getCapacity()
等等。
- 构造函数是...构造函数,这意味着只要项目构造或就会调用它们]创建。您绝对不应该以任何方式显式调用构造函数。
- 这是一个基本规则:无论何时使用
new
命令访问内存,都应该在一段时间后在某处调用 delete
。您的代码存在严重的内存泄漏。
我可能可以为您提供更多帮助,但我不完全理解您在某些方法中想要完成的工作,即 grow()
和 pushBack()
。
在构造函数体内通过赋值语句来初始化变量不是好的风格。相反,应该在进入构造函数主体之前初始化变量。
您可以使用 member initializer list 或在 class 定义中提供默认值来执行此操作。后者在这里似乎最简单:
class MyVector
{
private:
int arraySize = 0;
int arrayCapacity = 0;
int* theData = nullptr;
// ....
在构造函数中,您应该利用现有函数来做同样的事情,而不是复制代码:
MyVector::MyVector(int capacityIn)
{
// call function which increases capacity to match capacityIn.
}
目前您实际上没有增加容量的功能,因此您需要添加一个。 (grow()
函数使 int 变量增加,但您不会分配更多内存,因此这只会导致您的代码写入实际分配的 space 末尾)。
它可能看起来像:
void grow( int newCapacity )
{
if ( newCapacity < arrayCapacity )
return; // we do not need to shrink
int *newData = new int [new_capacity];
if ( arraySize > 0 )
std::copy(arrayData, arrayData + arraySize, newData);
delete[] arrayData;
newData = arrayData;
}
然后你可以修改grow()
(如果你还想保留那个),push_back()
也可以调用这个函数。
注意 clear()
函数只需要做 arraySize = 0;
。它不需要释放任何内存;您可以保留该容量以备将来使用。
更新:感谢您的快速回复。看来我发布了旧版本的代码。除了参数化构造函数之外,一切都保持不变。如您所见,代码中存在一些缺陷,但请记住,我还没有完全完成这个。目前我更担心数组,因为这是昨天介绍的新概念。 我尝试了几种不同的方法并研究了几个小时。大多数回复说只使用向量 class 但这是为了帮助我们理解内存分配和动态数组的家庭作业。目前这是给我带来问题的 .cpp 和 .h 文件。每次触发删除(或清除函数)操作时,都会发生错误,指出 blahblah.exe 已触发断点。
MyVector.h
#pragma once
class MyVector
{
private:
int arraySize;
int arrayCapacity;
int* theData;
void grow();
public:
MyVector();
MyVector(int n);
int size() const;
int capacity() const;
void clear();
void push_back(int n);
int& at(int n);
~MyVector();
};
MyVector.cpp
#include "MyVector.h"
#include <iostream>
using namespace std;
MyVector::MyVector()
{
arraySize = 0;
arrayCapacity = 0;
theData = new int[0];
}
MyVector::MyVector(int capacityIn)
{
theData = new int [capacityIn];
arraySize = 0;
arrayCapacity = 0;
}
int MyVector::size() const
{
return arraySize;
}
int MyVector::capacity() const
{
return arrayCapacity;
}
void MyVector::clear()
{
delete [] theData;
theData = nullptr;
}
void MyVector::push_back(int n)
{
if (arrayCapacity==0)
{
arrayCapacity++;
MyVector(arrayCapacity);
}
if (arraySize == arrayCapacity)
{
grow();
MyVector(arrayCapacity);
}
theData[arraySize] = n;
arraySize++;
}
int& MyVector::at(int index)
{
if (index >= 0 && index<arraySize)
{
return (theData[index]);
}
else
{
throw index;
}
}
void MyVector::grow()
{
arrayCapacity = arrayCapacity + arrayCapacity;
}
MyVector::~MyVector()
{
if (theData != nullptr)
{
clear();
}
}
这里:
MyVector::MyVector(int capacityIn)
{
int* theData = new int [capacityIn];
}
您声明了一个局部指针 theData
,它隐藏了当前对象的 theData
数据成员,使其未初始化。从那里开始,所有关于使用它的赌注都被取消了,它是你的程序最终崩溃的 delete[]
纯属偶然。写入
MyVector::MyVector(int capacityIn)
{
theData = new int [capacityIn];
}
相反,arraySize
和 arrayCapacity
也必须初始化。
除此之外,您将运行遇到
的问题MyVector(arrayCapacity);
在 push_back
函数中分配了一个 MyVector
类型的临时对象,该对象(几乎)立即再次被销毁;它不会更改当前对象。
你有很多问题我已经看到了:
- 您不应该像这样显式调用构造函数。它不会按照你的想法去做。将分配放在真正的成员函数中。
- 每次你 "grow" 你的数组,你只是分配新的,导致泄漏,因为以前的指针没有被删除。
- 您要问的主要问题:您甚至没有存储在构造函数中分配的指针。将
int* theData = new int [capacityIn];
更改为theData = new int [capacityIn];
。例如,您在第一个构造函数中做得正确。 - 您没有在第二个构造函数 (
MyVector(int)
) 中初始化arraySize
或arrayCapacity
。
吹毛求疵:
- 删除前无需检查
nullptr
。 - 没必要
new int[0]
。您永远不应该访问内存,因此只需将其初始化为nullptr
.
这导致您无法解决问题:
int* theData = new int [capacityIn];
你说的是:"Please define an integer pointer..."等等。成员变量不同于您在方法中定义的变量;这样做是没有意义的。相反,你应该这样做:
theData = new int [capacityIn];
或者,仅出于教育目的(并且为了让您理解我们正在分配给成员变量):
this->theData = new int [capacityIn];
另外(有些点可能不是那么重要,但因为你是新人,我想指出一下):
请在第二个构造函数中设置您的其他变量,您似乎忘记这样做了。
MyVector::MyVector(int capacityIn) { theData = new int [capacityIn]; arraySize = capacityIn; arrayCapacity = capacityIn; }
你应该有有意义的名字,
theData
是你绝对应该避免的。 http://petdance.com/2012/04/the-worlds-two-worst-variable-names/- 您的方法应以动词开头,例如
getDimension()
getCapacity()
等等。 - 构造函数是...构造函数,这意味着只要项目构造或就会调用它们]创建。您绝对不应该以任何方式显式调用构造函数。
- 这是一个基本规则:无论何时使用
new
命令访问内存,都应该在一段时间后在某处调用delete
。您的代码存在严重的内存泄漏。
我可能可以为您提供更多帮助,但我不完全理解您在某些方法中想要完成的工作,即 grow()
和 pushBack()
。
在构造函数体内通过赋值语句来初始化变量不是好的风格。相反,应该在进入构造函数主体之前初始化变量。
您可以使用 member initializer list 或在 class 定义中提供默认值来执行此操作。后者在这里似乎最简单:
class MyVector
{
private:
int arraySize = 0;
int arrayCapacity = 0;
int* theData = nullptr;
// ....
在构造函数中,您应该利用现有函数来做同样的事情,而不是复制代码:
MyVector::MyVector(int capacityIn)
{
// call function which increases capacity to match capacityIn.
}
目前您实际上没有增加容量的功能,因此您需要添加一个。 (grow()
函数使 int 变量增加,但您不会分配更多内存,因此这只会导致您的代码写入实际分配的 space 末尾)。
它可能看起来像:
void grow( int newCapacity )
{
if ( newCapacity < arrayCapacity )
return; // we do not need to shrink
int *newData = new int [new_capacity];
if ( arraySize > 0 )
std::copy(arrayData, arrayData + arraySize, newData);
delete[] arrayData;
newData = arrayData;
}
然后你可以修改grow()
(如果你还想保留那个),push_back()
也可以调用这个函数。
注意 clear()
函数只需要做 arraySize = 0;
。它不需要释放任何内存;您可以保留该容量以备将来使用。