30
std::map<std::string, std::string> myMap;

std::map<std::string, std::string>::iterator i = m_myMap.find(some_key_string);
if(i == m_imagesMap.end())
    return NULL;

string *p = &i->first;

最後の行は有効ですか?このポインタpを別の場所に保存したいのですが、プログラムの全期間にわたって有効ですか?しかし、このマップに(他の一意のキーを使用して)要素を追加したり、他のキーを削除したりすると、この文字列(キーと値のペア)が再割り当てされないため、pが無効になります。

4

4 に答える 4

59

セクション 23.1.2#8 (連想コンテナーの要件):

挿入メンバーは反復子とコンテナーへの参照の有効性に影響を与えず、消去メンバーは反復子と消去された要素への参照のみを無効にします。

そのため、その要素を削除しない限り、マップ要素のデータ メンバーへのポインターの保存は有効であることが保証されます

于 2009-02-05T14:24:56.633 に答える
22

まず、マップは安定していることが保証されています。つまり、イテレータは要素の挿入または削除によって無効化されません (もちろん削除される要素を除きます)。

ただし、イテレータの安定性はポインタの安定性を保証するものではありません! 通常、ほとんどの実装では (少なくともあるレベルでは) ポインターを使用してイテレーターを実装しますが (つまり、ソリューションが機能すると想定しても安全です)、実際に保存する必要があるのはイテレーター自体です。

あなたができることは、次のような小さなオブジェクトを作成することです:

struct StringPtrInMap
{
  typedef std::map<string,string>::iterator iterator;
  StringPtrInMap(iterator i) : it(i) {}
  const string& operator*() const { return it->first; }
  const string* operator->() const { return &it->first; }
  iterator it;
}

そして、文字列ポインターの代わりにそれを保存します。

于 2009-02-05T14:12:01.167 に答える
1

どの操作がイテレータを無効にするかわからない場合は、リファレンスで簡単に調べることができます。たとえば、vector::insertの場合、次のように表示されます。

これにより、ベクター サイズが効果的に増加し、新しいベクター サイズが現在のベクター容量を超えた場合にのみ、割り当てられたストレージ スペースが自動的に再割り当てされます。ベクター コンテナーでの再割り当てにより、以前に取得したすべての反復子、参照、およびポインターが無効になります。

一方、 map::insertはそのようなことについて何も言及していません。

ただし、ピエールが言ったように、ポインタではなくイテレータを保存する必要があります。

于 2009-02-05T14:25:14.683 に答える
0

なぜあなたはこれをしたいのですか?

const std::string であるため、*p の値を変更することはできません。変更した場合は、要素の並べ替え順序を変更することで、コンテナーの不変条件を壊す可能性があります。

ここで指定していない他の要件がない限り、文字列のコピーを取得する必要があります。

于 2009-02-06T14:29:02.053 に答える