c ++类析构函数删除一些但不是所有成员数据

时间:2018-03-15 16:31:16

标签: c++ destructor dynamic-arrays

我通过不同的资源阅读,但感觉我错过了什么。当变量(numItems)达到零时,我明确地调用析构函数。我有一个打印所有类对象(学生)的循环,但是任何调用析构函数的对象都有一个空白的名字和姓氏,ID和numItems变量仍然存在。我误解了析构函数是如何工作的吗?为什么要删除一些但不是全部的成员属性?

此外,“项目”存储在动态数组中。只要数组是公共的,我就可以设置和访问它们。但即使使用setter,如果我尝试填充私有数组,程序也会崩溃。

部首:

#ifndef STUDENT_H
#define STUDENT_H
#include <string>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define ARRAY_MAX 15
using namespace std;

class Student
{
private:
    string firstName, lastName;
    unsigned int ID, numItems = 0;
    typedef string* StringPtr;
    //StringPtr items;


public:
    int capacity = 15;
    string *items = new string[capacity];
    Student();
    Student(const unsigned int id, const string fName, const string lName);
    string getfName() const;
    string getlName() const;
    unsigned int getnumItems() const;
    string getItem(int num);
    unsigned int getID() const;
    void setfName(string fname);
    void setlName(string lname);
    void setID(unsigned int id);
    void setItem(string str, int num);
    int CheckoutCount();
    bool CheckOut(const string& item);
    bool CheckIn(const string& item);
    bool HasCheckedOut(const string& item);
    void Clear();
    ~Student();
    //const Student operator+(string rhs);
    //void operator+=(string rhs);
    //bool operator==(Student rhs);
    friend istream& operator>>(istream& input, Student& stu);
    friend ostream& operator<<(ostream& output, const Student& stu);

};
#endif // STUDENT_H

说明:

#include "student.h"

using namespace std;

Student::Student()
{
}

Student::Student(const unsigned int id, const string fName, const string lName)
{
    firstName = fName;
    lastName = lName;
    ID = id;
}

string Student::getfName() const
{
    return firstName;
}

string Student::getlName() const
{
    return lastName;
}

unsigned int Student::getnumItems() const
{
    return numItems;
}

string Student::getItem(int num)
{

    return items[num];
}

unsigned int Student::getID() const
{
    return ID;
}

void Student::setfName(string fname)
{
    firstName = fname;
}

void Student::setlName(string lname)
{
    lastName = lname;
}

void Student::setID(unsigned int id)
{
    if ((id >= 1000) && (id <= 100000))
    {
        ID = id;
    }
    else
    {
        cout << "Attempted ID for " << firstName << " " << lastName << " is invalid. Must be between 1000 and 100,000." << endl;
    }
}

void Student::setItem(string str, int num)
{
    items[num] = str;
}

int Student::CheckoutCount()
{
    return numItems;
}

bool Student::CheckOut(const string & item)
{
    if (this->HasCheckedOut(item) == true)
    {
        return false; // already found item in list, CheckOut failed...
    }
    else
    {
        items[numItems] = item;
        numItems++;
        return true; // CheckOut successful
    }

}

bool Student::CheckIn(const string & item)
{
    for (int i = 0; i < numItems; i++)
    {
        if (items[i] == item)
        {
            for (; i < numItems - 1; i++)
            {
                // Assign the next element to current location.             
                items[i] = items[i + 1];
            }

            // Remove the last element as it has been moved to previous index.
            items[numItems - 1] = "";
            numItems = numItems - 1;
            if (numItems == 0)
            {
                this->~Student();
            }
            return true;
        }
    }
    return false;

}

bool Student::HasCheckedOut(const string & item)
{
    string *end = items + numItems;
    string *result = find(items, end, item);
    if (result != end)
    {
        return true; // found value at "result" pointer location...
    }
    else
        return false;
}

void Student::Clear()
{
    ID = 0;
    firstName = "";
    lastName = "";
    delete[] items;
}

Student::~Student()
{
}

istream & operator>>(istream & input, Student & stu)
{
    string temp;
    input >> stu.ID >> stu.firstName >> stu.lastName >> stu.numItems;
    int loopnum = stu.numItems;
    if (loopnum > 0)
    {
        for (int i = 0; i < loopnum; i++)
        {
            input >> temp;
            stu.setItem(temp, i);
        }
    }
    return input;
}

ostream & operator<<(ostream & output, const Student & stu)
{
    string s = stu.firstName + " " + stu.lastName;
    output << setw(8) << stu.ID << setw(16) << s << setw(8) << stu.numItems;
    int loopnum = stu.numItems;
    if (loopnum > 0)
    {
        for (int i = 0; i < loopnum; i++)
        {
            output << stu.items[i] << "  ";
        }
    }
    output << endl << endl;
    return output;
}

主:

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include "student.h"
using namespace std;

void fcheck(ifstream &mystream);

int main()
{
    ifstream sin("students.txt");           // File input/output variables
    ifstream fin("checkins.txt");
    ifstream chin("checkouts.txt");
    ofstream sout("UpdatedStudentsC.txt");
    Student stu1, stu2;

    fcheck(sin);
    fcheck(fin);
    fcheck(chin);

    typedef Student* StuPtr;
    StuPtr studentList;
    int stud_capacity = 50;
    studentList = new Student[stud_capacity];
    int num_studs = 0;


    sout << std::setiosflags(std::ios::left); // justify output to format properly.
    while (sin.good())              // While there's data in the file, do stuff.
    {
        sin >> stu1;

        stu1.CheckIn("Towel");
        stu1.CheckIn("Locker");
        if (stu1.getnumItems() == 0)
        {
            stu1.~Student();
        }
        studentList[num_studs] = stu1;
        num_studs++;

        sout << stu1; 
    }

    for (int i = 0; i < 16; i++)
    {
        cout << studentList[i].getID() << " " << studentList[i].getfName() << "  " << studentList[i].getnumItems() <<  endl;
    }

    system("pause");

    // Close files
    fin.close();
    chin.close();
    sout.close();
    sin.close();

    // Quit without error
    return 0;
}

void fcheck(ifstream &mystream)
{
    if (!mystream)                          // If we can't find the input file, quit with error message.
    {
        cout << "file not opened!" << endl;
        system("pause");
        exit(1);
    }
}

2 个答案:

答案 0 :(得分:1)

如果你不告诉它,析构函数会删除任何内容(就像现在一样,你的析构函数是空的)。析构函数用于在释放对象之前执行一些清理,但它不会解除分配。

隐式调用析构函数

  • 当堆栈对象超出范围时,
  • 使用delete解除分配堆对象时。

答案 1 :(得分:0)

  

当任何调用了析构函数的对象都有一个空白的名字和姓氏时,ID和numItems变量仍然存在。

已销毁对象的所有成员变量都不存在。

无法在C ++中检查对象是否已被销毁。当您尝试访问已销毁对象的成员时,该程序将具有未定义的行为。一种可能的行为可能是您可能从被破坏的对象中得到的东西,而另一种可能的行为可能是您没有预料到的。

您调用本地自动变量const test = [ 0, 0, 0, 0, 0.0000050048828125, 0.0000137939453125, 0.000049560546875, 0.00008740234375, 0.00015966796875, 0.000262451171875, 0.0003975830078125, 0.0005687255859375, 0.0007802734375, 0.001037353515625, 0.0013468017578125, 0.00172119140625, 0.0021756591796875, 0.0027232666015625, 0.0033880615234375, 0.004206787109375, 0.0052380371093750005, 0.006586181640625, 0.008400146484375001, 0.010904296875, 0.0144892578125, 0.0196798095703125, 0.049684204101562504, 0.0886883544921875, 0.11185363769531251, 0.134164306640625, 0.137352294921875, 0.1160369873046875, 0.08516308593750001, 0.0539765625, 0.014997436523437501, -0.015882568359375, -0.0387554931640625, -0.06125732421875, -0.0745780029296875, -0.07479357910156251, -0.0725338134765625, -0.0418538818359375, 0.08582861328125001, 0.397717529296875, 0.8136408691406251, 1.2295617980957032, 0.9944150390625001, 0.2824605712890625, -0.38949267578125, -0.597251220703125, -0.425675537109375, -0.1537947998046875, -0.0500914306640625, -0.0111041259765625, 0.0027451171875, 0.0071739501953125, 0.008443359375, 0.0094327392578125, 0.012530517578125, 0.0176046142578125, 0.0300162353515625, 0.0433489990234375, 0.056962646484375004, 0.0704832763671875, 0.0770511474609375, 0.0898175048828125, 0.10311853027343751, 0.117046142578125, 0.1312630615234375, 0.1529300537109375, 0.167607177734375, 0.1899068603515625, 0.2124422607421875, 0.235044677734375, 0.2575535888671875, 0.2724073486328125, 0.286978271484375, 0.3007579345703125, 0.3067425537109375, 0.3106370849609375, 0.303756103515625, 0.2897236328125, 0.25916931152343753, 0.2200599365234375, 0.1728209228515625, 0.133416259765625, 0.086224853515625, 0.05493408203125, 0.02409423828125, 0.00922607421875, -0.0043409423828125, -0.0097349853515625, -0.013127685546875, -0.01423095703125, -0.013834716796875, -0.012556030273437501, -0.010675048828125, -0.00835888671875, -0.0057305908203125, -0.0000562744140625 ]; //calc the result for Step 1 step1 = test.reduce(function(pre, cur, index, orgArray){ if(cur === 0){pre['found'].push({'type':'no-signal','index':index,'value':0});pre['min']={'value':0,'index':0};pre['max']={'value':0,'index':0};return pre;} if(pre['max']['value'] < cur) { pre['max']={'value':cur,'index':index}; if(pre['max']['value']>orgArray[index+1]){pre['found'].push({'type':'upwave','index':index,'value':cur})}; } if(pre['min']['value'] > cur) { pre['min']={'value':cur,'index':index}; if(pre['min']['value']<orgArray[index+1]){pre['found'].push({'type':'downwave', 'index':index,'value':cur})}; } if(orgArray[index-1] > 0 && cur < 0){pre['found'].push({'type':'down-cross','index':index});pre['min']={'value':0,'index':0};pre['max']={'value':0,'index':0};} if(orgArray[index-1] < 0 && cur > 0){pre['found'].push({'type':'up-cross','index':index});pre['max']={'value':0,'index':0};pre['min']={'value':0,'index':0};} return pre },{'max':{'value':0,'index':0}, 'min':{'value':0,'index':0}, 'found':[]}) //console.log(step1['found']); //Calc the final result final = step1['found'].reduce(function(pre, cur, index, orgArray){ if(cur.type==='downwave' && orgArray[index-1].type==='down-cross' && orgArray[index-2].type==='upwave' ) { pre.push({'type':'S', 'index':cur.index, 'value':cur.value}); } if(cur.type==='downwave' && (index+1 < orgArray.length && orgArray[index+1].type==='up-cross' ) && (index+1 < orgArray.length && orgArray[index+2].type==='upwave') ) { pre.push({'type':'Q', 'index':cur.index, 'value':cur.value}); } if(cur.type==='upwave' && orgArray[index-1].type==='up-cross' && (index+1 < orgArray.length && orgArray[index+1].type==='down-cross') ) { pre.push({'type':'R', 'index':cur.index, 'value':cur.value}); } return pre; }, []); console.log(final);的析构函数,但您没有构建新对象。当变量超出范围时,它将被再次销毁#34;。这也会导致程序具有未定义的行为。需要明确调用析构函数是非常罕见的情况,并非如此。