2009-06-01 6 views
27

私はこのようなコードを持っている:C++ポインタのデフォルトのコンストラクタは何ですか?

class MapIndex 
{ 
private: 
    typedef std::map<std::string, MapIndex*> Container; 
    Container mapM; 

public: 
    void add(std::list<std::string>& values) 
    { 
     if (values.empty()) // sanity check 
      return; 

     std::string s(*(values.begin())); 
     values.erase(values.begin()); 
     if (values.empty()) 
      return; 

     MapIndex *mi = mapM[s]; // <- question about this line 
     if (!mi) 
      mi = new MapIndex(); 
     mi->add(values); 
    } 
} 

私が持っている主な関心事は、新しいアイテムがマップに追加された場合MAPM [s]の式がNULLポインタへの参照を返すかどうかですが?

SGI docsはこれを言う:特定のキーに関連付けられているオブジェクトへの参照を返し DATA_TYPE &オペレータ[](CONST key_type & K)。マップにそのようなオブジェクトが含まれていない場合、operator []はデフォルトオブジェクトdata_type()を挿入します。だから、私の質問は、かどうかデフォルトのオブジェクトDATA_TYPE()の挿入は、NULLポインタを

が作成されますされ、またはそれはメモリのどこかに向いて無効なポインタを作成することができますか?

答えて

20

はとにかく無効なポインタ:) data_type()がデフォルトの初期化オブジェクトに評価

+5

私はそれが無効であることに気をつけませんが、 "安全"であることを願っています。あなたは0のポインタを簡単にチェックすることができ、その上で "削除"を呼び出すことができます。これについて読むための参照(URL)? –

+0

私は手元にリファレンスがありません。しかし、私はポインタのコンストラクタが0に初期化することを確信しています( 'int'、' short' ...のようなすべての整数型のように)。 –

+20

C++標準、8.5段落5: 'タイプTのオブジェクトをデフォルトで初期化することは、そうでなければ(PODでも配列でもない)、オブジェクトはゼロで初期化されます。' Tがスカラー型(3.9)であれば、オブジェクトはT(T)に変換された0(ゼロ)の値に設定されます。同じ標準では、3.9、段落10: '算術型(3.9.1)、列挙型、ポインタ型、およびメンバ型へのポインタ(3.9.2)、[...]を総称してスカラー型と呼びます。だから、ポインタはデフォルトで0に初期化されます。 –

2

式ですNULL(0)ポインタを、作成します。非POD型の場合、デフォルトのコンストラクタが呼び出されますが、ポインタなどのPOD型の場合、デフォルトの初期化はゼロ初期化に相当します。

だから、NULLポインタを作成してマップに頼ることができます。説明はPseudo Constructor Initializersを参照してください。

18

はい、stlコンテナは、明示的に格納されていないオブジェクトをデフォルトで初期化するため、ゼロ(NULL)ポインタにする必要があります(マップ内に存在しないキーにアクセスしたり、サイズ)。

C++標準、8.5段落5つの状態:

デフォルト初期化する タイプTのオブジェクトを意味する:

  • をT非PODクラス型(句クラス)である場合、 Tのデフォルト コンストラクタが呼び出され(及び 初期Tが有する場合悪い形成さ ないアクセスデフォルトコンストラクタ)は
  • Tが配列型である場合、各要素は、デフォルトではありません初期化された
  • それ以外の場合は、オブジェクトの記憶域がゼロ初期化されます。

また、デフォルトの初期化はコンストラクタを単純に省略することとは異なります。コンストラクタを省略してシンプルな型を宣言すると、不確定な値が返されます。

int a; // not default constructed, will have random data 
int b = int(); // will be initialised to zero 
3

UPDATE:私は私のプログラムを完了し、私が求めていたまさにその行は、それが時々クラッシュする原因となったが、後の段階でされています。問題は、std :: mapに格納されたポインタを変更せずに新しいオブジェクトを作成していることです。本当に必要なのは、参照またはそのポインタへのポインタです。私は誰もがこれを気づいていない驚いて

MapIndex* &mi = mapM[s]; // <- question about this line 
if (!mi) 
    mi = new MapIndex(); 
mi->add(values); 

MapIndex *mi = mapM[s]; // <- question about this line 
if (!mi) 
    mi = new MapIndex(); 
mi->add(values); 

に変更する必要があります。この文とクラッシュについて確認が、definetelyメモリリークない

0

場合(マイル!) MI =新しいあるMapIndex();

は、ポインタmiがmapMが何を保持しているかを参照していないので、常にtrueを返します。 は、sの特定の値です。

また、通常のポインタの使用を避け、boost :: shared_ptrまたは破損したときにメモリを解放する他のポインタ を使用します。これにより、mapM.clear()またはerase() を呼び出すことができます。マップに格納されているキーと値のデストラクタを呼び出す必要があります。もし、値があなたのポインタのようなPODならば、手動で削除されない限り、デストラクタは呼び出されません。 マップ全体を反復するとメモリリークが発生します。

関連する問題