我是否以正确的方式插入STL地图?它不会泄漏记忆吗?

时间:2012-07-07 18:21:02

标签: c++ stl map

以下代码100%正确吗?我正在编写一个游戏,CItemElem是一个包含Item信息的类,例如权力等。我想将项目中的指针存储到另一个名为CChatLink的类的实例中。请看一下:

[H]

#pragma once

class CChatLink
{
private:
    CChatLink(){}; //no new usage or global object allowed
    ~CChatLink(){}; 
public:
    BOOL InsertChatLink( TCHAR* szText, CItemElem *pItemElem );
    map<std::string,CItemElem*>m_mChatLink;
    static CChatLink* GetInstance( void )
    {
        static CChatLink pObj;
        return &pObj;

    }

};

[CPP]

#include "StdAfx.h"
#include "Item.h"
#include "CChatLink.h"

BOOL CChatLink::InsertChatLink( TCHAR *szText, CItemElem* pItemElem )
{
    if( pItemElem && szText )
    {
        std::string szInsert( szText );
        CItemElem *pItem = new CItemElem; //as far as I know, it must be allocated on the heap to be inserted ^^
        pItem = pItemElem;
        m_mChatLink.insert( make_pair( szInsert, pItem ) );
        return TRUE;
    }
    return FALSE;
}

我可以将std::string以这种方式存储到map吗?

(我目前正在学习C ++,所以请放轻松我。)

4 个答案:

答案 0 :(得分:4)

是的,你这里有内存泄漏:

CItemElem *pItem = new CItemElem;
pItem = pItemElem;

您刚刚丢失了分配对象的地址。如果要插入的项目作为参数传递,为什么还要执行此操作?你的代码并不清楚。

这是你的意思吗?:

BOOL CChatLink::InsertChatLink( TCHAR *szText, CItemElem* pItemElem )
{
    if( pItemElem && szText )
    {
        std::string szInsert( szText );
        m_mChatLink.insert( make_pair( szInsert, pItemElem ) );
        return TRUE;
    }
    return FALSE;
}

修改

听起来pItemElem是指向已在堆栈上分配的对象的指针。您可以将m_mChatLink更改为std::map<std::string, CItemElem>(而不是CItemElem*)或者这样:

CItemElem pItem = new CItemElem;
*pItem = *pItemElem;
m_mChatLink.insert(make_pair(szInsert, pItem));

您的析构函数中需要delete所有这些CItemElem

答案 1 :(得分:3)

字符串很好,但是在这里:

CItemElem *pItem = new CItemElem;

您正在创建一个永远不会被删除的动态分配的CItemElem。事实上,你在这里立即丢失了句柄:

pItem = pItemElem;

您必须确保插入到地图中的指针指向正确的对象,并且,如果此对象是动态分配的,那么您的类必须在必要时处理删除此元素,例如当删除元素时从地图中,或当CChatLink类本身被销毁时。

鉴于插入方法的签名是这样的:

BOOL InsertChatLink( TCHAR* szText, CItemElem *pItemElem );

然后有两个选择:

  1. 调用者拥有指向的对象,因此您的类不需要担心删除它。但在这种情况下,指向对象必须至少与CChatLink实例一样长。这必须有详细记录。
  2. 您的CChatLink班级拥有所有权。在这种情况下,它负责删除,并且调用者必须知道这一点。这必须有详细记录。
  3. 您应该查看smart pointers,它为不同的所有权方案提供自动管理(独特的所有权,如上例所示,共享所有权,无所有权)。

    另一个选择是完全忘记指针并按值CItemElems存储:

    class CChatLink {
      std::map<std::string, CItemElem> m_mChatLink;
     public:
      BOOL InsertChatLink( TCHAR* szText, const CItemElem& item ) {
        ...
        m_mChatLink.insert( make_pair( szInsert, item ) );
        ...
      }
    };
    

答案 2 :(得分:2)

字符串没有内存泄漏,因为std :: string正确管理自己的内存。你确实有CItemElem的泄密:你正在创建它但从不删除它(至少在显示的代码中)。

有几个选择:

  • 从聊天链接中删除CItemElem实例时,请明确删除它们。
  • 使用智能指针管理CItemElem指针。一些流行的智能指针实现选择包括:

请注意,您不希望使用std::auto_ptr,因为它无法添加到C ++标准库容器中。

答案 3 :(得分:1)

在类中分配动态内存时。您需要编写复制构造函数和赋值运算符。如果没有指针被复制/分配,内存在析构函数时被删除两次。