使用类析构函数删除动态数组

时间:2015-10-03 16:26:58

标签: c++ arrays class

我有一个简单的程序,它使用两个类存储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并以某种方式打印我们第一次打印的相同数据。

显然数据没有被删除。但为什么?为什么这种情况有时只会发生,有时候只会直接出现故障?

1 个答案:

答案 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是当对象超出范围时,您不必担心在该对象上调用deletedelete[]并且您正在防止可能的内存泄漏。如果您的编译器支持,我也会用{0}替换任何带有nullptr的原始指针,但是大多数(如果不是所有的)现代编译器现在应该已经支持它了。如果您打算使用NULLnew运算符,请不要在类声明中使用此功能。

delete | delete []

我会建议这个

private:
    Stock* data;

我希望这可以帮助你。

修改

我还注意到,在StockManagement类中,您定义了一个指向Stock对象的指针,该对象是一个类对象,然后在构造函数中将其初始化为private: std::shared_ptr<Stock> data; // Or std::unique_ptr<Stock> data; NULL,但在您的内部您在nullptr上调用delete []的析构函数。通常data用于指针数组,我在代码中没有看到这些指针。你有一个成员函数来使用带括号运算符的new来分配内存,但你只是将你的成员变量定义为指向对象的指针,而不是指向对象指针的指针。