0

次のコードは 100% 正しいですか? 私はゲームをコーディングしており、パワーなどの情報CItemElemを保持するクラスです。アイテムからのポインタを という名前の別のクラスのインスタンスに格納したいと考えています。ご覧ください:ItemCChatLink

[.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

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_mChatLinka std::map<std::string, CItemElem>(not a CItemElem*)に変更するか、次のように変更できます。

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

デストラクタでdeleteこれらすべてのsが必要になります。CItemElem

于 2012-07-07T18:26:47.310 に答える
3

文字列は問題ありませんが、ここでは:

CItemElem *pItem = new CItemElem;

削除されない動的に割り当てられたものを作成していますCItemElem。実際、ここではすぐにハンドルを失います。

pItem = pItemElem;

マップに挿入するポインターが正しいオブジェクトを指していることを確認する必要があります。また、このオブジェクトが動的に割り当てられている場合は、マップから要素が削除された場合など、必要に応じてクラスがこの要素を削除する必要があります。 、またはCChatLinkクラス自体が破棄されたとき。

挿入メソッドのシグネチャが次のようになっているとします。

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

次に、2 つのオプションがあります。

  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_ptrC++ 標準ライブラリ コンテナーに追加できないため、使用しないことに注意してください。

于 2012-07-07T18:28:48.687 に答える
1

クラスに動的メモリを割り当てる場合。コピー コンストラクターと代入演算子を記述する必要があります。そうしないと、ポインタがコピー/割り当てられ、デストラクタ時にメモリが2回削除されます。

于 2012-07-07T18:27:22.193 に答える