访问 std::map 键和值

发布于 2024-10-10 08:34:30 字数 320 浏览 7 评论 0原文

如何访问 std::map 的键或值的 std::vector

谢谢。

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

这本质上就是我想做的:

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

// fill map

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

How do you access an std::vector of the keys or values of an std::map?

Thanks.

Edit: I would like to access the actual elements, not just copies of their contents. essentially I want a reference, not a copy.

This is essentially what I am wanting to do:

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

// fill map

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

场罚期间 2024-10-17 08:34:30

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

You can't do that because neither the values nor the keys are laid out consecutively in memory. Each key/value pair is allocated independently in memory. In a situation like yours, you have to copy the values around.

温柔嚣张 2024-10-17 08:34:30

没有一个函数可以调用来从 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 关键字。 此处对此有很好的解释。

希望这有帮助!

There isn't a single function you can call to get all of the keys or values from an STL map. Instead, you can use the map iterators to access this information:

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

If you want to write a function that takes these values and wraps them up in an STL vector, then you could do so like this:

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;
}

Note that in these template functions, the type of the iterator is

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

instead of

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

This is because const_iterator here is a dependent type - a type that depends on a template argument - and consequently for silly historical reasons must be prefaced by the typename keyword. There's a good explanation of this here.

Hope this helps!

寄居者 2024-10-17 08:34:30

正如其他人在他们的答案中所说,如果不复制它们,就无法访​​问 std::vector 形式的所有键或值 - std::map 不是为这种形式的访问而设计的。

对于您的情况,我将设置 2 个容器:

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

其中向量存储 ID,映射的值是向量中 ID 的索引。添加新纹理时,使用push_back()将ID添加到向量中,其索引存储在具有最后一个元素索引的映射条目中,例如:

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 后调用:

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

... 因为 std::vector 保证元素在内存中彼此连续。


编辑:更改了地图的值类型;这以前是 GLuint*,指向向量的元素。感谢 Oli Charlesworth 指出了这个设计的缺陷。
编辑:添加示例代码

As others have said in their answers, you can't access all the keys or values in the form of a std::vector without copying them - std::map isn't designed for this form of access.

For your situation, I would set up 2 containers:

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

where the vector stores the ID, and the map's value is the index to the ID in the vector. When you add a new texture, add the ID into the vector with push_back(), whose index is stored in a map entry with the last element's index, e.g.:

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
}

The push_back would maintain the same indexes for old IDs. Encapsulate all this within a class with functions to add and search for textures, just like in the answer to your other question.

This would let you call, after the IDs are loaded:

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

... since std::vector guarantees that elements are consecutive to one another in memory.


edit: changed the map's value type; this was previously GLuint*, pointing at the vector's elements. Thanks to Oli Charlesworth for pointing out this design's flaw.
edit: added sample code

我家小可爱 2024-10-17 08:34:30

除了其他人所说的之外,听起来很像您真的想将值放入 std::vector 中,然后对向量进行排序;这样你就可以像你想要的那样访问内容(即通过指向它们的连续数组的指针)。

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

Further to what others have said, it sounds very much like you really want to put the values into a std::vector and then sort the vector; that way you can access the contents like you want to (i.e. via a pointer to a contiguous array of them).

Note that this assumes that reading will be your bottleneck, and that writing (i.e. setting up the vector) will be done relatively infrequently. If not, then you're probably better off sticking with the std::map, and then copying the contents into a temporary array/vector every time you want to use them in this fashion.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文