类中的赋值运算符,_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));

assignment operator in class, _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));

本文关键字:VALID pHead- gt nBlockUse IS BLOCK 赋值运算符 ASSERTE TYPE      更新时间:2023-10-16

我目前有一个赋值运算符,如下所示:

CellPhoneHandler CellPhoneHandler:: operator=(const CellPhoneHandler &original){
   if (this->nrOfCellphones > 0)
        for (int i = 0; i < this->nrOfCellphones; i++) {
             delete this->cellphone[i];
   }

    delete[] cellphone;
    this->nrOfCellphones = original.nrOfCellphones;
    this->cellphone = new CellPhone*[this->nrOfCellphones];

    for (int i = 0; i<this->nrOfCellphones; i++) 
    {
        cellphone[i] = original.cellphone[i];
    }
    return *this;
}

然后在程序开始时,我打算测试它是否正常工作:

    CellPhoneHandler assignme;
assignme.addPhone("assignment phone", 500, 1000);
assignme.addPhone("assignment phone 2", 500, 1000);
copyme = assignme;

Hower,当我退出程序时,我得到和未处理的异常,该异常指向 dbgdel 中的第 52 行.cpp:

       /* verify block type */
        _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));

有什么想法吗?问题似乎只在于这个函数,因为当我将测试从程序中评论出来时,它会起作用。

我的手机类看起来像这样:

    class CellPhone
{
private:
    string model;
    int stock;
    double price;
public:
    CellPhone(string model="", int stock=0, double price=0); // constructor
    string getModel()const;
    int getStock()const;
    double getPrice()const;
    void setModel(string model);
    void setStock(int stock);
    void setPrice(double price);
    string toString() const;
    ~CellPhone(); //destructor
};

已将变量名称更改为原始变量,但错误仍然相同。

class CellPhoneHandler
{
private:
    CellPhone **cellphone;
    int nrOfCellphones;
public:
    CellPhoneHandler();
    CellPhoneHandler(const CellPhoneHandler &original); 
    CellPhoneHandler operator=(const CellPhoneHandler &original); 
    void addPhone(string model, int price, int stock);
    ~CellPhoneHandler();
    string showByStock(int stock) const;
    void removeModel(string model);
    void changePriceProcent(double procent, int price);
    void showAll(string array[], int nrOfCellphones) const;
    void saveToFile(string fileName) const;
    void readFromFile(string fileName);
    int getNrOfPhones()const;
}; 

更新:将我的运算符=更改为此简化代码:

CellPhoneHandler CellPhoneHandler:: operator=(const CellPhoneHandler &original){
CellPhoneHandler tmp(original);
swap(this->cellphone, tmp.cellphone);
swap(this-> nrOfCellphones, tmp.nrOfCellphones);
return *this;
}

该程序现在可以工作了,但是,这是深入复制吗?我的老师告诉我,我的上一次作业没有这样做。

赋值运算符应该返回一个CellPhoneHandler&,而不是一个CellPhoneHandler对象。 通过返回对象,您将(不必要地)调用复制构造函数。

此外,赋值运算符无法检查自赋值(将CellPhoneHandler对象分配给自身)。 自赋值最终将删除对象的数据,然后尝试从已删除的内存区域复制。

如果对new[]的调用引发异常,赋值运算符也将失败。 在发出对new[]的调用之前,您正在更改对象的内部结构,从而在出现问题并引发异常时损坏对象new[]

但是,与其编写所有这些代码来实现赋值运算符,不如利用复制构造函数和析构函数来实现复制/交换习惯用法的赋值运算符:

#include <algorithm>
//...
CellPhoneHandler& CellPhoneHandler:: operator=(const CellPhoneHandler &original)
{
    CellPhoneHandler temp(original);
    std::swap(temp.nrOfCellphones, nrOfCellphones);
    std::swap(temp.cellphone, cellphone);
    return *this;
}

现在,它通过创建一个临时对象来使用复制构造函数,并且只需将临时对象的内部与当前对象的内部交换即可。 然后临时对象就消失了。

这是异常安全的(因为如果构造temp出现任何问题,原始对象不会发生任何事情),并且不需要检查自赋值(您可以这样做以进行可能的优化,但不需要实际执行此检查,这与你最初尝试赋值运算符不同)。