10

std::map::findデータのコピーを取得するのではなく、データへのポインターを返し、それを使用するのは危険ですか?

現在、マップ内のエントリへのポインタを取得し、それを別の関数に渡してデータを表示しています。ポインタが無効になる原因となるアイテムの移動が心配です。これは正当な懸念ですか?

ここに私のサンプル関数があります:

MyStruct* StructManagementClass::GetStructPtr(int structId)

{
    std::map<int, MyStruct>::iterator foundStruct;
    foundStruct= myStructList.find(structId);
    if (foundStruct== myStructList.end())
    {
        MyStruct newStruct;
        memset(&newStruct, 0, sizeof(MyStruct));
        myStructList.structId= structId;
        myStructList.insert(pair<int, MyStruct>(structId, newStruct));

       foundStruct= myStructList.find(structId);
   }

   return (MyStruct*) &foundStruct->second;

}

4

4 に答える 4

9

おそらくほとんど違いはありませんが、ポインタよりもイテレータを返す方が間違いなく一般的です。

有効性を維持する限り、マップ反復子は、それが参照するアイテムがマップから削除/消去されるまで有効です。

マップ内の他のノードを挿入または削除すると、マップ内のノードが再配置される可能性があります。ただし、これはノード間のポインターを操作することによって行われるため、関心のあるノードへのポインターを含む他のノードを変更しますが、その特定のノードのアドレスやコンテンツは変更しないため、そのノードへのポインター/イテレーターは有効なままです。

于 2013-05-08T14:09:00.960 に答える
3

あなた、あなたのコード、および開発チームが std::map 値 ( の後に有効、、、またはのinsert後に無効) の有効期間を理解している限り、 、、 、またはを使用することはすべて有効です。また、戻り値が常に存在することが保証されている場合は、、またはも有効です。eraseclearassignoperator=iteratorconst_iterator::mapped_type*::mapped_type const*::mapped_type&::mapped_type const&

賢明なことに、私は変更可能なバージョンよりもconstバージョンを好み、イテレーターよりもポインターよりも参照を好みます。

イテレータとポインタを返すのは良くない:

  • 実装の詳細を公開します。
  • .second結果が std::pair であり、実際の値を取得するために 呼び出さなければならないことを、呼び出し元が反復子を逆参照することを知る必要があるため、使用するのは厄介です。
    • .firstユーザーが気にしないかもしれないキーです。
  • イテレータが無効かどうかを判断するには、 の知識が必要ですが::end()、これは明らかに呼び出し元には利用できません。
于 2013-05-08T14:19:10.970 に答える
0

はい、

使い方を知らずにジェネリック関数を作成すると、無効になる可能性があるため、ポインター (またはイテレーター) を返すのは危険です。


1. std::shared_ptr を操作して、それを返します。(下記参照)
2. 構造体を値で返す (遅くなる可能性があります)

//change the difination of the list to
std::map<int, std::shared_ptr<MyStruct>>myStructList;

std::shared_ptr<MyStruct> StructManagementClass::GetStructPtr(int structId)
{
    std::map<int, std::shared_ptr<MyStruct>>::iterator foundStruct;
    foundStruct = myStructList.find(structId);
    if (foundStruct == myStructList.end())
    {
        MyStruct newStruct;
        memset(&newStruct, 0, sizeof(MyStruct));
        myStructList.structId= structId;
        myStructList.insert(pair<int, shared_ptr<MyStruct>>(structId, shared_ptr<MyStruct>(newStruct)));

       foundStruct= myStructList.find(structId);
   }

   return foundStruct->second;
于 2013-05-08T14:41:45.607 に答える