简体   繁体   English

引用作为 std::map 中的键

[英]Reference as key in std::map

Suppose some data structure:假设一些数据结构:

typedef struct {
    std::string s;
    int i;
} data;

If I use the field data.s as key when adding instances of data in a map of type std::map<std::string&, data> , do the string gets copied?如果我在std::map<std::string&, data>类型的 map 中添加data实例时使用字段data.s作为键,是否会复制字符串? Is it safe to erase an element of the map because the reference will become invalid?擦除 map 的元素是否安全,因为引用将变为无效?

Also do the answers to these questions also apply to an unordered_map ?这些问题的答案也适用于unordered_map吗?

EDIT:编辑:

This is my current solution... but adding iterator to the map is UGLY:这是我目前的解决方案......但是将迭代器添加到 map 是丑陋的:

typedef struct {
    const std::string* s;
    int i;
} data;

std::map<std::string, data> map;
typedef std::map<std::string, data>::iterator iterator;

// add an element to the map
iterator add_element(const std::string& s) {
    std::pair<iterator, bool> p = states.insert(std::make_pair(s, data()));
    iterator i = p.first;
    if(p.second) {
        data& d = (*i).second;
        d.s = &(*i).first;
    }
    return i;
}

C++11 C++11

Since C++11 reference wrapper is part of standard.由于 C++11 参考包装器是标准的一部分。

#include <functional> 

std::map<std::reference_wrapper<std::string>, data>

Using Boost使用提升

You may want to take a look at boost.ref .您可能想看看boost.ref It provides a wrapper that enables references to be used in STL-containers like this:它提供了一个包装器,使引用能够在 STL 容器中使用,如下所示:

std::map<boost::reference_wrapper<std::string>, data>

You can't store references in Standard Library containers - your map should look like:您不能在标准库容器中存储引用 - 您的地图应如下所示:

map <string,data> mymap;

The map will manage both the key string and the struct instances, which will be copies, for you.映射将为您管理键字符串和结构实例,它们将是副本。 Both map and unordered_map work in the same way in this regard, as do all other Standard Library containers. mapunordered_map在这方面的工作方式相同,所有其他标准库容器也是如此。

Note that in C++, you don't need typedefs to declare structs:请注意,在 C++ 中,您不需要 typedef 来声明结构:

struct data {
    std::string s;
    int i;
};

You cannot use the reference.您不能使用参考。 The map can copy the content.地图可以复制内容。 This is I guess implementation dependent.我猜这取决于实现。

But tested with the microsoft STL.但是用微软STL测试过。

struct data
{
            data(data const& rhs)
            {
               a new object will be created here
            }
            std::string s;
            int i; 
};

Add some objects to the map and you will run into the copy constructor.向地图添加一些对象,您将遇到复制构造函数。 This should invalidate your reference.这应该会使您的参考无效。

I don't think there's a big performance gain if you choose pointer instead of object.如果您选择指针而不是对象,我认为不会有很大的性能提升。 Only do this if you're managing data with lot of existing string objects which need to hold inside the container.仅当您使用大量需要保存在容器内的现有字符串对象来管理数据时才这样做。 Also the destruction of the objects has to be managed manually before destructing the container.此外,必须在销毁容器之前手动管理对象的销毁。

Regarding your question about unordered_map , std::reference_wrapper will not work in the case.关于您关于unordered_map的问题, std::reference_wrapper在这种情况下不起作用。

std::reference_wrapper is not a default constructible class. std::reference_wrapper不是默认的可构造 class。 To create a hasher, std::unordered_map needs type of the key to be a default constructible, copy assignable, destructible, and swappable class.要创建哈希器, std::unordered_map需要键的类型是默认的可构造、可复制、可破坏和可交换的 class。 See the std::hash .请参阅std::hash

You could try write your own reference_wrapper which would be a default constructible class, and use your class as the key type for a std::unordered_map specialization.您可以尝试编写自己的reference_wrapper ,这将是一个默认的可构造 class,并使用您的 class 作为std::unordered_map专业化的键类型。 To check whether your class satisfy each criterion mentioned above, use related functions from the type_traits library.要检查您的 class 是否满足上述每个标准,请使用type_traits库中的相关函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM