以下代码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 ++,所以请放轻松我。)
答案 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 );
然后有两个选择:
CChatLink
实例一样长。这必须有详细记录。CChatLink
班级拥有所有权。在这种情况下,它负责删除,并且调用者必须知道这一点。这必须有详细记录。您应该查看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
的泄密:你正在创建它但从不删除它(至少在显示的代码中)。
有几个选择:
请注意,您不希望使用std::auto_ptr
,因为它无法添加到C ++标准库容器中。
答案 3 :(得分:1)
在类中分配动态内存时。您需要编写复制构造函数和赋值运算符。如果没有指针被复制/分配,内存在析构函数时被删除两次。