注意事项:使用容器存放带有指针变量的类对象时一定要重载复制构造函数。下面示例说明:
定义两个类:
class DataItemRegValue
{
public:
BYTE ModBusType;
short DataMark;
BYTE RegisterCnt;
public:
DataItemRegValue();
virtual ~DataItemRegValue();
};
class DataItem
{
public:
BYTE ModBusType;
BYTE DeviceNo;
BYTE DataCnt;
/// <summary>
/// 数据项
/// </summary>
vector<DataItemRegValue>* m_pItemList;
public:
DataItem(const BYTE& modbusType);
DataItem(const DataItem& data);
virtual ~DataItem();
public:
int GetLength();
int ReadBuffer(const int& pos, BYTE* pBuffer);
};
//DataItem
DataItem::DataItem(const BYTE& modbusType)
{
ModBusType = modbusType;
ModBusType = 0;
DeviceNo = 0;
DataCnt = 0;
//堆上分配内存。
m_pItemList = new vector<DataItemRegValue>();
}
//复制构造函数,加入容器时,或通过复制创建一个新的对象时调用它。
DataItem::DataItem(const DataItem& data)
{
this->DataCnt = data.DataCnt;
this->DeviceNo = data.DeviceNo;
this->ModBusType = data.ModBusType;
this->m_pItemList = new vector<DataItemRegValue>();
this->m_pItemList->assign(data.m_pItemList->begin(),data.m_pItemList->end());
}
//析构函数,释放内存。
DataItem::~DataItem()
{
if(m_pItemList != nullptr)
{
m_pItemList->clear();
delete m_pItemList;
m_pItemList = nullptr;
}
}
//调用
其中m_pItemList定义为vector容器:
vector<DataItem>* m_pItemList = new vector<DataItem>();
int ReadBuffer(const int& pos, BYTE* pBuffer,const int& nBufferSize)
{
if (pos < 0 || pBuffer == nullptr)
{
return -1;
}
CUnPacket unpk(pos, pBuffer);
int CurIndex = unpk.GetCurIndex();
for (; CurIndex < nBufferSize; )
{
DataItem item(ModBusType);
item.ReadBuffer(CurIndex, pBuffer);
CurIndex += item.GetLength();
/*m_pItemList是一个容器,注意了,在数据被push_back到容器中时,会调用DataItem的复制构造函数。如果没有重载DataItem的复制构造函数,则系统会调用默认的复制构造函数,这样,同一个指针值存放在两个不同的指针变量中,DataItem变量构造了两次,声明局部变量时调用构造函数创建对象,在数据push_back到容器中时调用了复制构造函数创建了另一个对象放入容器m_pItemList中,当这两个对象调用析构函数销毁时,同一个指针值指向同一块内存,被析构了两次,从而导致异常报误。*/
m_pItemList->push_back(item);
}
return 0;
}