访问std :: map键和值

时间:2011-01-05 00:19:35

标签: c++ dictionary vector stdvector stdmap

如何访问std::vector的{​​{1}}个键或值?

感谢。

编辑:我想访问实际的元素,而不仅仅是其内容的副本。基本上我想要一个参考,而不是副本。

这基本上就是我想要做的事情:

std::map

4 个答案:

答案 0 :(得分: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有一个很好的解释。

希望这有帮助!

答案 1 :(得分:2)

你不能这样做,因为值和键都没有在内存中连续排列。每个键/值对在内存中独立分配。在像你这样的情况下,你必须复制周围的值。

答案 2 :(得分:0)

除了别人所说的,听起来非常像你真的想把值放到std::vector然后对矢量进行排序;这样你就可以像你想要的那样访问内容(即通过指向它们连续数组的指针)。

请注意,这假定读数将是您的瓶颈,并且写入(即设置向量)将相对不频繁地完成。如果没有,那么你最好坚持使用std::map,然后每次想要以这种方式使用它们时将内容复制到临时数组/向量中。

答案 3 :(得分: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指出这个设计的缺陷。 编辑:添加示例代码