1

std::vectorのキーまたは値にどのようにアクセスしますstd::mapか?

ありがとう。

編集:コンテンツのコピーだけでなく、実際の要素にアクセスしたいと思います。基本的に、コピーではなく参照が必要です。

これは本質的に私がやりたいことです:

std::map<std::string, GLuint> textures_map;

// fill map

glGenTextures( textures_map.size(), &textures_map.access_values_somehow[0] );
4

4 に答える 4

3

値もキーもメモリ内に連続して配置されていないため、これを行うことはできません。各キーと値のペアは、メモリ内で個別に割り当てられます。あなたのような状況では、値コピーする必要があります。

于 2011-01-05T00:47:34.913 に答える
2

STL マップからすべてのキーまたは値を取得するために呼び出すことができる単一の関数はありません。代わりに、マップ反復子を使用してこの情報にアクセスできます。

for (map<K, V>::iterator itr = myMap.begin(); itr != myMap.end(); ++itr) {
    // Access key as itr->first
    // Access value as itr->second
}

これらの値を取得して STL ベクトルにラップする関数を作成する場合は、次のようにします。

template <typename K, typename V>
std::vector<K> GetKeys(const std::map<K, V>& m) {
    std::vector<K> result;
    result.reserve(m.size()); // For efficiency

    for (typename std::map<K, V>::const_iterator itr = m.begin(); itr != m.end(); ++itr)
         result.push_back(itr->first);

    return result;
}

template <typename K, typename V>
std::vector<V> GetValues(const std::map<K, V>& m) {
    std::vector<V> result;
    result.reserve(m.size()); // For efficiency

    for (typename std::map<K, V>::const_iterator itr = m.begin(); itr != m.end(); ++itr)
         result.push_back(itr->second);

    return result;
}

これらのテンプレート関数では、反復子の型が

typename std::map<K, V>::const_iterator

それ以外の

std::map<K, V>::const_iterator

これは、const_iteratorここに依存型(テンプレート引数に依存する型) があるためです。したがって、ばかげた歴史的理由により、typenameキーワードを前に付ける必要があります。これについての良い説明がありますhere

お役に立てれば!

于 2011-01-05T00:24:05.950 に答える
0

他の人が言ったことに加えて、値を a に入れてからstd::vectorベクトルを並べ替えたいと本当に思っているように聞こえます。そうすれば、必要に応じてコンテンツにアクセスできます (つまり、それらの連続した配列へのポインターを介して)。

これは、読み取りがボトルネックになり、書き込み (ベクトルの設定) が比較的頻繁に行われないことを前提としていることに注意してください。std::mapそうでない場合は、この方法で使用するたびに、 に固執し、内容を一時的な配列/ベクトルにコピーすることをお勧めします。

于 2011-01-05T01:21:54.930 に答える
0

他の人が答えで言ったように、 std::vector の形式ですべてのキーまたは値にアクセスすることはできません。それらをコピーせずに- std::map はこの形式のアクセス用に設計されていません。

あなたの状況では、2 つのコンテナーをセットアップします。

std::vector<GLuint> texture_id;
std::map<std::string, size_t> texture_map;

ここで、ベクトルは ID を格納し、マップの値はベクトル内の ID へのインデックスです。新しいテクスチャを追加するときは、ID を でベクターに追加しますpush_back()。そのインデックスは、最後の要素のインデックスと共にマップ エントリに保存されます。例:

pair<map<string, size_t>::iterator, bool> result = 
    texture_map.insert(make_pair(new_texture_name, -1));    //ignore the index for now
if(result.second) { //true when the texture name isn't already in the map
    texture_id.push_back(new_id);
    result.first->second = texture_id.size()-1; //update the index in the map to this ID's element in texture_id
}

push_back は、古い ID に対して同じインデックスを維持します。他の質問への回答と同様に、テクスチャを追加および検索する関数を使用して、これらすべてをクラス内にカプセル化します。

これにより、ID がロードされた後に呼び出すことができます。

glGenTextures( textures_id.size(), &(textures_id[0]) );

... std::vector は、要素がメモリ内で互いに連続していることを保証するためです。


編集: マップの値のタイプを変更しました。これは以前は GLuint* で、ベクトルの要素を指していました。この設計の欠陥を指摘してくれた Oli Charlesworth に感謝します。編集:サンプルコードを追加

于 2011-01-05T09:40:48.807 に答える