被类的向量弄糊涂了:;The Big Three";,在pushback之后删除类,以及资源管理



我有一个这样的类:

class cSerialMessage
{
public:
cSerialMessage(const enumMessages type, std::string txmessage = "") {rxAnswer="";};
// Get/Set Methods
// ...
bool AddIntParam();     // Stores an int as parameter for the message
void BuildCompleteMessage() // Build the whole message following the protocol rules
private:
enumMessages m_type;
std::string m_txmessage, m_rxanswer;
// [...]
};

然后我有另一个"管理"消息队列的类:

class cMsgManager
{
public:
cMsgManager();
// [...]
cSerialMessage* NewMessage(eMessages MSG);
bool AddParameter(int Param);
bool QueueMessage(bool FirstPosition);
private:
deque<cSerialMessage> cMS;
cSerialMessage* tempMsg;
}

相关部分是创建cSerialMessage并将其添加到deque的地方。

cSerialMessage* cMsgManager::NewMessage (eMessages MSG)
{
// Begin the creation of a new message

if (tempMsg!=nullptr) {
// there was already a temporary message
OutputDebugString ("NOPE!");
return nullptr;
}
tempMsg = new cSerialMessage(MSG);
return tempMsg;
}
//------------------------------------------------------------------------------
bool cMsgManager::AddParameter (int Param)
{
if (tempMsg==nullptr) {
// this means that NewMessage() was'nt called before.
OutputDebugString ("NOPE!);
return false;
}
return tempMsg->AddIntParam(Param);
}
//------------------------------------------------------------------------------
bool cMsgManager::QueueMessage(bool FirstPosition)
{
if (tempMsg==nullptr) {
// this means that NewMessage() was'nt called before.
OutputDebugString ("NOPE!);
return false;
}
// Build the final message
tempMsg->BuildCompleteMessage();
if (FirstPosition) {
cMS.push_front(*tempMsg);
}else{
cMS.push_back(*tempMsg);
}
delete tempMsg;
tempMsg=nullptr;
return true;
}

尽管有关于这个话题的所有问题(这是非常详细的(,我仍然感到困惑。

我应该删除我的tempMsg吗?它是在deque中复制的,还是最终,tempMsg指向的数据是稍后从deque访问的数据?或者我必须创建复制构造函数和复制赋值运算符吗?

  1. 我应该删除我的tempMsg吗

是的,正如所写的,您必须将delete作为tempMsg,或者在程序的生命周期中重用单个实例(不能将new作为第一个实例之后的实例(。重复使用它可能需要在每次重复使用之前将其清除,这似乎不值得

  1. 它是在deque中复制的,还是最终,tempMsg指向的数据是稍后将从deque访问的数据

它被复制了;push_back接收引用,但被记录只是为了复制或移动(由于您传递了一个l值,它将被复制(。您可以通过执行cMS.push_front(std::move(*tempMsg));来节省一些工作,从而清空tempMsg(因为您稍后将删除它,所以您还可以保存副本(。

  1. 或者让我创建复制构造函数和复制赋值运算符

假设cSerialMessage的所有成员本身都是可复制的(没有原始指针等(,并且您没有定义任何自定义的复制/移动操作或析构函数,那么您应该没事;编译器生成的复制构造函数将正常工作。另一方面,cMsgManager需要3/5构造函数和析构函数的完整规则,因为您没有为tempMsg使用智能指针或值语义。

请注意,整个动态分配是毫无意义/浪费的。您可以将tempMsg设为cSerialMessage(而不是cSerialMessage*(,然后按值处理它。您可以将其保留为实例的属性,或者只让NewMessage返回实际的新消息,而不在本地存储副本。本地副本将使线程或可重入代码成为噩梦,因此按值返回新消息,并让调用方管理它可能是一个更好的主意。

我应该删除tempMsg吗?是的,你创建了它,必须有人删除它,而那应该是你。

它被复制到deque了吗?不,tempMsg所指向的对象被复制到deque中,但tempMsg之后仍然存在,并且它所指向的目标仍然存在,因此需要删除。

我必须创建复制构造函数和复制赋值运算符吗?是的,或者如果您对cMsgManager不可复制感到满意,则将其标记为已删除。

相关内容

最新更新