您如何访问 anstd::vector
的键或值std::map
?
谢谢。
编辑:我想访问实际元素,而不仅仅是其内容的副本。本质上我想要一个参考,而不是副本。
这基本上是我想要做的:
std::map<std::string, GLuint> textures_map;
// fill map
glGenTextures( textures_map.size(), &textures_map.access_values_somehow[0] );
您如何访问 anstd::vector
的键或值std::map
?
谢谢。
编辑:我想访问实际元素,而不仅仅是其内容的副本。本质上我想要一个参考,而不是副本。
这基本上是我想要做的:
std::map<std::string, GLuint> textures_map;
// fill map
glGenTextures( textures_map.size(), &textures_map.access_values_somehow[0] );
你不能这样做,因为值和键都不是在内存中连续布局的。每个键/值对在内存中独立分配。在像您这样的情况下,您必须复制周围的值。
没有一个函数可以调用来从 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
关键字开头。这里有一个很好的解释。
希望这可以帮助!
根据其他人所说的,这听起来很像您真的想将值放入 astd::vector
然后对向量进行排序;这样你就可以访问你想要的内容(即通过指向它们的连续数组的指针)。
请注意,这假设读取将成为您的瓶颈,并且写入(即设置向量)将相对不频繁地进行。如果没有,那么您最好坚持使用std::map
,然后每次您想以这种方式使用它们时将内容复制到临时数组/向量中。
正如其他人在他们的回答中所说的那样,您无法以 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 指出这个设计的缺陷。编辑:添加示例代码