C++ 被类的向量弄糊涂了:“;“三巨头”;,在回推后删除类,以及资源管理

C++ 被类的向量弄糊涂了:“;“三巨头”;,在回推后删除类,以及资源管理,c++,vector,copy-constructor,C++,Vector,Copy Constructor,我有一门课是这样的: class cSerialMessage { public: cSerialMessage(const enumMessages type, std::string txmessage = "") {rxAnswer="";}; // Get/Set Methods // ... bool AddIntParam(); // Stores an int as parameter for the

我有一门课是这样的:

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;
}
尽管有关于这个主题()的所有问题,我仍然感到困惑

我应该删除我的临时消息吗?它是在deque中复制的,还是最终由TEMPMG指向的数据是稍后将从deque访问的数据?
或者我必须创建复制构造函数和复制赋值操作符吗?

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

它被复制到德克了吗?不,由
tempMsg
指向的内容将复制到数据块中,但
tempMsg
之后仍然存在,并且它指向的对象仍然存在,因此需要删除


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

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

它被复制到德克了吗?不,由
tempMsg
指向的内容将复制到数据块中,但
tempMsg
之后仍然存在,并且它指向的对象仍然存在,因此需要删除

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

  • 我应该删除我的临时消息吗
  • 是的,如前所述,您必须
    删除
    您的
    tempMsg
    ,或者在程序的生命周期中重复使用单个实例(在第一个实例之后不创建新的
    实例)。重用它可能需要在每次重用之前清除它,这似乎不值得

  • 它是在deque中复制的,还是最终由TEMPMG指向的数据是稍后将从deque访问的数据
  • 它是复制的
    push_back
    接收引用,但仅记录用于复制或移动(并且由于您传递了一个l值,它将进行复制)。通过执行
    cMS.push_front(std::move(*tempMsg)),可以节省一些工作
    以便清空
    tempMsg
    (因为您只是在之后将其删除,所以您最好保存副本)

  • 或者我必须创建复制构造函数和复制赋值操作符
  • 假设
    cSerialMessage
    的所有成员本身都是可正确复制的(没有原始指针等),并且您还没有定义任何自定义复制/移动操作或析构函数,那么您就可以了;编译器生成的复制构造函数可以正常工作<另一方面,code>cMsgManager
    需要3/5构造函数和析构函数的完整规则,因为您没有为
    tempMsg
    使用智能指针或值语义

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

  • 我应该删除我的临时消息吗
  • 是的,如前所述,您必须
    删除
    您的
    tempMsg
    ,或者在程序的生命周期中重复使用单个实例(在第一个实例之后不创建新的
    实例)。重用它可能需要在每次重用之前清除它,这似乎不值得

  • 它是在deque中复制的,还是最终由TEMPMG指向的数据是稍后将从deque访问的数据
  • 它是复制的
    push_back
    接收引用,但仅记录用于复制或移动(并且由于您传递了一个l值,它将进行复制)。通过执行
    cMS.push_front(std::move(*tempMsg)),可以节省一些工作
    以便清空
    tempMsg
    (因为您只是在之后将其删除,所以您最好保存副本)

  • 或者我必须创建复制构造函数和复制赋值操作符
  • 假设
    cSerialMessage
    的所有成员本身都是可正确复制的(没有原始指针等),并且您还没有定义任何自定义复制/移动操作或析构函数,那么您就可以了;编译器生成的复制构造函数可以正常工作<另一方面,code>cMsgManager
    需要3/5构造函数和析构函数的完整规则,因为您没有为
    tempMsg
    使用智能指针或值语义


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

    此代码不应按原样编译<代码>cMS.向前推(tempMsg)
    应为错误,因为
    tempMsg
    cSerialMessage*
    cMS
    保留
    cSerialMessage
    。除非有原因,否则
    tempMsg
    应该是
    cSerialMessage
    ,而不是
    cSerialMessage*
    deque
    保存
    cSerialMessage
    的副本。我完全不明白为什么要在显示的其余代码中使用指针和
    new
    。作为第一个近似值,如果删除代码中的所有
    *
    ,它将
    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;
    }