【问题标题】:Destructor problems+ list display [duplicate]析构函数问题+列表显示[重复]
【发布时间】:2016-02-07 00:05:30
【问题描述】:

我有以下代码: 问题是当我在 main 类型中创建一个列表时:Reteta。 显示列表后,我收到错误分配错误。如果我从 Reteta 类中评论析构函数,程序就可以工作。你能帮我找出错误吗?或者也许我没有很好地显示列表,所以程序还有其他问题需要处理。 代码如下:

#include<iostream>
#include<fstream>
#include<list>
using namespace std;

class Medicament{
private:
    char *denumire;
    float pret;
public:
    Medicament()
    {
        this->pret = 0;
        this->denumire = new char[strlen("Fara denumire")];
        strcpy(this->denumire, "Fara denumire");
    }
    Medicament(char* denumire, float pret)
    {
        this->denumire = new char[strlen(denumire) + 1];
        strcpy(this->denumire, denumire);
        this->pret = pret;
    }
    Medicament(const Medicament& x)
    {
        this->denumire = new char[strlen(x.denumire) + 1];
        strcpy(this->denumire, x.denumire);
        this->pret = x.pret;
    }
    ~Medicament()
    {
        if (this->denumire)
        {
            delete[] this->denumire;
        }
    }
    void setDenumire(char *x)
    {
        if (x)
        {
            if (this->denumire)
            {
                delete[] this->denumire;
            }
            this->denumire = new char[strlen(x) + 1];
            strcpy(this->denumire, x);
        }
    }
    char* getDenumire()
    {
        return this->denumire;
    }
    void setPret(float f)
    {
        if (f)
        {
            this->pret = f;
        }
    }
    Medicament operator=(Medicament x)
    {
        this->denumire = new char[strlen(x.denumire) + 1];
        strcpy(this->denumire, x.denumire);
        this->pret = x.pret;
        return *this;
    }
    friend ostream& operator<<(ostream& consola, Medicament &x)
    {
        consola << "Medicament: " << x.denumire << endl; //error here
        consola << "Pret: " << x.pret << endl;
        return consola;
    }
    float getPret()
    {
        return this->pret;
    }
    friend class Reteta;
};

class Reteta{
protected:
    Medicament *medicamente;
    int n;
public:
    Reteta()
    {
        this->n = 0;
        this->medicamente = NULL;
    }
    Reteta(Medicament *v, int n)
    {
        this->n = n;
        this->medicamente = new Medicament[n];
        for (int i = 0; i < n; i++)
        {
            this->medicamente[i] = v[i];
        }
    }
    ~Reteta()
    {
        if (this->medicamente)
        {
            delete[] this->medicamente;   //The problem is here. If I comment this the program works.
        }
    }
    int getN()
    {
        return this->n;
    }

    friend ostream& operator<<(ostream& consola, Reteta& x)
    {
        consola << "Numar de medicamente: " << x.n << endl;
        consola << "    -->Lista Medicamente<-- "<<endl;
        for (int i = 0; i < x.n; i++)
        {
            consola << x.medicamente[i].getDenumire() <<endl; //error at this line when I compile
            consola << x.medicamente[i].getPret()<< endl;

        }
        return consola;
    }
    void adaugaMedicament(Medicament x)
    {
        Reteta y;
        y.medicamente= new Medicament[this->n+1];
        for (int i = 0; i < this->n; i++)
        {
            y.medicamente[i] = this->medicamente[i];
        }
        y.medicamente[this->n] = x;
        delete[] this->medicamente;
        this->medicamente = new Medicament[this->n + 1];
        this->n++;
        for (int i = 0; i < this->n; i++)
        {
            this->medicamente[i] = y.medicamente[i];
        }
    }
    Medicament operator[](int i)
    {
        if (i >= 0 && i < this->n)
        {
            return this->medicamente[i];
        }
    }
    friend class RetetaCompensata;
    virtual float getValoare()
    {
        float sum = 0;
        for (int i = 0; i < this->n; i++)
        {
            sum=sum+this->medicamente[i].getPret();
        }
        return sum;
    }
    friend ifstream& operator>>(ifstream& consola, Reteta& x)
    {
        char aux[30];
        float z;
        consola >> x.n;
        if (x.medicamente)
            delete[] x.medicamente;
        x.medicamente = new Medicament[x.n];
        for (int i = 0; i < x.n; i++)
        {
            consola >> aux >> z;
            Medicament m(aux, z);
            x.medicamente[i] = m;
        }
        return consola;
    }
};

class RetetaCompensata : public Reteta{
private:
    float procentCompensat;
public:
    RetetaCompensata(float procent)
    {
        this->procentCompensat = procent;
    }
    RetetaCompensata(Reteta r, float procent)
    {

        this->procentCompensat = procent;
        this->n = r.n;
        this->medicamente = new Medicament[r.n];
        for (int i = 0; i < r.n; i++)
        {
            this->medicamente[i] = r.medicamente[i];
        }
    }
    float getValoare()
    {
        float sum = 0;
        sum = this->procentCompensat*this->getValoare();
        return sum;
    }

    friend ostream& operator<<(ostream& consola, RetetaCompensata &x)
    {
        consola << "**Procent compensat: " << x.procentCompensat << endl;
        consola << "Numar de medicamente: " << x.n << endl;
        consola << "    -->Lista Medicamente<-- " << endl;
        for (int i = 0; i < x.n; i++)
        {
            consola << x.medicamente[i] << " ";
        }
        return consola;
    }
};

void main()
{
    //1
    Medicament nurofen("Nurofen", 11.25f);
    Medicament aspirina = nurofen;
    aspirina.setDenumire("Aspirina");
    aspirina.setPret(4.5f);
    Medicament bixtonim("Bixtonim", 8.2f);
    Medicament temp;
    temp = nurofen;
    cout << temp << endl;
    cout << nurofen << endl;
    cout << aspirina << endl;
    //2
    Medicament medicamente[] = { aspirina, nurofen };
    Reteta r0(medicamente, 2);
    cout << r0 << endl;
    //3
    Reteta r1;
    r1.adaugaMedicament(nurofen);
    r1.adaugaMedicament(aspirina);
    for (int i = 0; i < r1.getN(); i++)
    {
        cout << r1[i] << endl;
    }
    //4
    RetetaCompensata r2(0.5);
    r2.adaugaMedicament(bixtonim);
    r2.adaugaMedicament(aspirina);


    RetetaCompensata r3(r1, 0.2);
    cout << "AFISARE R3" << endl;
    cout << r3 << endl << endl;
    Reteta* p = &r1;
    cout <<"Valoare reteta r1: "<< p->getValoare() << endl;
    //5
    Reteta r4;
    ifstream fisier("retete.txt");
    fisier >> r4;
    cout << r4 << endl;
    //6
    cout << endl << "Afisare Lista :" << endl << endl << endl;
    list<Reteta> R;
    list<Reteta>::iterator it;
    R.push_back(r0);
    R.push_back(r1);
    R.push_back(r3);
    R.push_back(r2);
    R.push_back(r4);
    for (it = R.begin(); it != R.end(); it++)
    {
        cout << *it << "  Valoare Reteta: " << it->getValoare() << endl << endl << endl; // error at this line when I compile 
    }
}

【问题讨论】:

  • Medicament operator=(Medicament x) 赋值运算符应该返回一个引用,而不是一个新对象。为什么不使用std::string 而不是char *?单独这样做会削减您编写的代码的主要部分。
  • 我是新手。我必须这样做。几周后我将只玩 STL。
  • 应该是相反的。现在使用 STL,稍后使用指针(很久以后)。
  • 当您的类在构造函数中分配内存并在析构函数中释放内存时,您必须正确实现复制构造函数和复制赋值运算符。
  • 嗯..您使用的是std::list而不是std::string?说真的,如果您使用 std::string 而不是 char *std::vector&lt;Medicament&gt; 而不是 new Medicament[n],那么所有这些代码都可以工作。

标签: c++ list stl destructor


【解决方案1】:

这是内存覆盖:

    this->denumire = new char[strlen("Fara denumire")];
    strcpy(this->denumire, "Fara denumire");

您没有为终止空字符分配空间:

    this->denumire = new char[strlen("Fara denumire") + 1];
    strcpy(this->denumire, "Fara denumire");

但是,当您有 std::string 可用时,为什么要这样做呢?仅此一项不仅可以缓解此类错误,而且您无需为 Medicament 类编写赋值运算符、复制构造函数或析构函数。


另一个错误是您的Reteta 类缺少复制构造函数和赋值运算符,因此由于Medicament* 成员,它不能安全地复制。然后,您将此类用作std::list&lt;Reteta&gt; 中的类型。

由于Reteta 不能安全地复制,而std::list 进行复制,因此您进入了未定义行为的世界。因此,您必须为Reteta 类提供适当的复制/赋值运算符。

【讨论】:

  • 责备我的老师 :)) 在 30 小时内我在 PO 进行了期末考试。所以我们不得不使用 *char 等。STL 就像考试的 10%。那么错误是什么?如果我从 Reteta 类中删除析构函数,它就可以工作..
  • 第 116 行和第 265 行是问题
  • “由于 Reteta 不是安全可复制的,并且 std::list 进行复制,因此您进入了未定义行为的世界。因此您必须为 Reteta 类提供适当的复制/赋值运算符。”这是我的问题。我创建了这些运算符并开始工作。谢谢你的时间保罗!
猜你喜欢
  • 2012-10-26
  • 1970-01-01
  • 1970-01-01
  • 2013-04-06
  • 2010-10-28
  • 2014-06-28
  • 2018-07-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多