0

以下代码 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::stringmap

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

4

4 回答 4

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_mChatLinkstd::map<std::string, CItemElem>( 不是CItemElem*) 或者这个:

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

您将需要在您的析构函数中使用delete所有这些CItemElems。

于 2012-07-07T18:26:47.310 回答
3

字符串很好,但在这里:

CItemElem *pItem = new CItemElem;

您正在创建一个CItemElem永远不会被删除的动态分配。实际上,您在这里立即失去了对它的控制:

pItem = pItemElem;

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

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

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

那么有两种选择:

  1. 调用者拥有指向的对象,所以你的类不需要担心删除它。但在这种情况下,指向的对象必须至少与您的CChatLink实例一样长。这必须有据可查。
  2. 你的CChatLink班级拥有所有权。在这种情况下,它负责删除,调用者必须意识到这一点。这必须有据可查。

您应该看一下智能指针,它为不同的所有权场景提供自动管理(唯一所有权,如上例所示,共享所有权,无所有权)。

另一种选择是完全忘记指针并存储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 ) );
    ...
  }
};
于 2012-07-07T18:24:25.883 回答
2

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

有几个选项:

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

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

于 2012-07-07T18:28:48.687 回答
1

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

于 2012-07-07T18:27:22.193 回答