我有一个简单的程序,它使用两个类存储3个变量的集合,一个名为Stock
,其中包含3个变量定义,以及基本的检查器和mutator函数,以及第二个函数{{1它有一个指向StockManagement
的指针和一些其他函数,可以执行各种操作,例如创建Stock
的动态数组,将文件数据转储到我们刚刚创建的数组中,等等类推。
在创建东西(例如构造函数,数组,输入数据,读取数据)方面一切正常但是当涉及到析构函数时,程序有可能会在delete命令中出现错误,如果没有时间,数据仍然可以出于某种原因访问。
以下是我认为是代码的重要部分
标头文件
Stock
Cpp文件(正确的名称让我逃脱)
class Stock {
private:
char tag[5];
int cost;
long volume;
public:
void setTag(char);
void setCost(int);
void setVolume(long);
char* getTag();
int getCost();
long getVolume();
}
class StockManagement {
private:
Stock* data;
int size;
public:
StockManagement();
~StockManagement();
// other functions
}
因此,在调用析构函数的时候,总会有数据存在。总是调用一个函数来获取文件中的行数(并将其保存为...
void Stock::setTag(char tag) {
this->tag = tag;
}
void Stock::setCost(int cost) {
this->cost = cost;
}
void Stock::setVolume(long volume) {
this->volume = volume;
}
char* Stock::getTag() {
return this->tag;
}
int Stock::getCost() {
return this->cost;
}
long Stock::getVolume() {
return this->volume;
}
// --
StockManagement::StockManagement() {
data = NULL;
size = 0;
}
StockManagement::~StockManagement() {
if (data != NULL) {
std::cout << data[0].getTag() << std::endl; // Debug line
delete [] data;
std::cout << data[0].getTag() << std::endl; // Debug line
data = NULL;
size = 0;
}
}
void StockManagement::allocateMemory() {
data = new Stock[size];
}
...
),用于分配内存,然后将数据输入到数组中。
然后是时候使用析构函数了。正如预期的那样,第一个cout线将始终输出。然后有可能从那时起发生两件事。我们在删除行中查出错误,或者我们检查它,调用第二个cout并以某种方式打印我们第一次打印的相同数据。
显然数据没有被删除。但为什么?为什么这种情况有时只会发生,有时候只会直接出现故障?
答案 0 :(得分:0)
你的构造函数和析构函数都有。
StockManagement::StockManagement() {
data = NULL;
size = 0;
}
StockManagement::~StockManagement() {
if (data != NULL) {
std::cout << data[0].getTag() << endl; // Debug line
delete [] data;
std::cout << data[0].getTag() << endl; // Debug line
data = NULL;
size = 0;
}
}
由于您的构造函数没有任何问题,但作为个人偏好,我更喜欢这个:
StockManagement::StockManager() :
data( nullptr ),
size( 0 )
{}
对于析构函数,我在代码中看到了一个问题
StockManagement::~StockManagement() {
if ( data != NULL ) {
std::cout << data[0].getTag() << endl; // Debug Line
delete[] data;
std::cout << data[0].getTag() << endl; // Debug Line
data = NULL;
size = 0;
}
}
我看到一些错误,可以优化以便于阅读。你的第一个错误是你正在使用std :: cout所以我假设你没有定义using namespace std;
。这意味着您还需要使用范围解析运算符以及endl;你需要把它声明为...... std::endl;
您的第二个错误是在您调用delete [] data;
之后,然后您在下一行尝试访问数据索引0处的元素并调用getTag()方法。这是未定义的行为,可能导致崩溃,未处理的异常等。
至于可读性,您的类成员中的命名约定可能会使用一些工作。还有一点需要考虑的是,对于您班级中的任何指针成员,您可以根据需要使用std::unique_ptr<ClassType>
或std::shared_ptr<ClassType>
。如果此类具有对象的唯一所有权,并且您不希望任何外部对象修改它,则使用unique,但如果您需要其他对象来处理此数据成员,则修改然后该类将保存您可以使用共享的已修改数据。独特之美shared是当对象超出范围时,您不必担心在该对象上调用delete
或delete[]
并且您正在防止可能的内存泄漏。如果您的编译器支持,我也会用{0}替换任何带有nullptr的原始指针,但是大多数(如果不是所有的)现代编译器现在应该已经支持它了。如果您打算使用NULL
和new
运算符,请不要在类声明中使用此功能。
delete | delete []
我会建议这个
private:
Stock* data;
我希望这可以帮助你。
修改强>
我还注意到,在StockManagement类中,您定义了一个指向Stock对象的指针,该对象是一个类对象,然后在构造函数中将其初始化为private:
std::shared_ptr<Stock> data;
// Or
std::unique_ptr<Stock> data;
或NULL
,但在您的内部您在nullptr
上调用delete []
的析构函数。通常data
用于指针数组,我在代码中没有看到这些指针。你有一个成员函数来使用带括号运算符的new来分配内存,但你只是将你的成员变量定义为指向对象的指针,而不是指向对象指针的指针。