1

您如何访问 anstd::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关键字开头。这里有一个很好的解释。

希望这可以帮助!

于 2011-01-05T00:24:05.950 回答
0

根据其他人所说的,这听起来很像您真的想将值放入 astd::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;

其中vector存储了ID,map的值是向量中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 回答