简体   繁体   English

指针作为映射C ++ STL中的键

[英]Pointers as keys in map C++ STL

I have a question on how pointers to a custom object are handled when used as Keys in an map. 我有一个问题,当在映射中用作键时如何处理指向自定义对象的指针。 More specifically if I define 更具体地说,如果我定义

std::map< CustomClass*, int > foo;

Would the default C++ implementation work to handle these pointers? 默认的C ++实现是否可以处理这些指针? Or do I need to define a custom comparator function to handle it? 还是我需要定义一个自定义比较器函数来处理它? In general, is it good practice to use pointers to objects as keys? 通常,将对象的指针用作键是否是一种好习惯?

The default implementation will compare the addresses stored by the pointers, so different objects will be considered as different keys. 默认实现将比较指针存储的地址,因此不同的对象将被视为不同的键。 However, the logical state of the object will not be considered. 但是,将不考虑对象的逻辑状态。 For example, if you use std::string * as the key, two different std::string objects with the same text of "Hello" would be considered a different key! 例如,如果您使用std::string *作为键,则具有相同文本"Hello"两个不同的std::string对象将被视为不同的键! (When stored in the map by their addresses) (按地址存储在地图中)

It's ok to use pointers as keys so long as you understand the important difference above. 只要您了解上述重要区别,就可以将指针用作键。

Pointers will be handled but compared as pointers (memory order). 将处理指针,但将其作为指针进行比较(内存顺序)。 You have to pass custom less functor if you wish to compare the objects: 如果要比较对象,则必须通过自定义less函子:

template<class T> struct ptr_less {
    bool operator()(T* lhs, T* rhs) {
        return *lhs < *rhs; }};
map<Object*,int,ptr_less<Object>> mymap;

C ++标准为指针提供了std::less专业化,因此可以安全地将它们用作映射键等。

Pointers can be used as keys but especially with a std::map (or std::set) I would not advise it. 指针可以用作键,但是特别是在std :: map(或std :: set)中,我不建议这样做。 The behavior of the program is not deterministic ie when one iterates over the map the order in which the items in the map are iterated is not guaranteed to be the same . 程序的行为不是确定性的,即,当在地图上进行迭代时,不能保证迭代地图中的项目的顺序是相同的 It really depends on the memory address of the object (key). 它实际上取决于对象(键)的内存地址。 Take a look at this example, as you can see irrespective of the insertion order into the map the items are iterated in a deterministic way when the key is a string rather than a pointer. 看一下这个示例,您可以看到,无论键在映射中的插入顺序如何,当键是字符串而不是指针时,都以确定性方式迭代项目。

http://ideone.com/VKirct http://ideone.com/VKirct

#include <iostream>
#include <map>
using namespace std;

class SomeClass {
    public:
    SomeClass(const std::string& name): m_name(name) {}
    std::string GetName()const {return m_name; }
    bool operator <(const SomeClass& rhs) const { return m_name < rhs.m_name; }
    private:
    std::string m_name;
};

auto print_seq  = [](const auto& seq) { for (const auto& itr: seq) {std::cout << itr.second << " , ";} std::cout << std::endl;};

int main() {
    // your code goes here
    std::map<SomeClass*, std::string> pointer_keyed_map;
    SomeClass s3("object3");
    SomeClass s1("object1");
    SomeClass s2("object2");
    pointer_keyed_map.insert(std::make_pair(&s1, s1.GetName()));
    pointer_keyed_map.insert(std::make_pair(&s2, s2.GetName()));
    pointer_keyed_map.insert(std::make_pair(&s3, s3.GetName()));
    std::cout << "Pointer based keys: object order" << std::endl;
    print_seq(pointer_keyed_map);

    std::map<SomeClass, std::string> int_keyed_map;
    int_keyed_map.insert(std::make_pair(s3, s3.GetName()));
    int_keyed_map.insert(std::make_pair(s1, s1.GetName()));
    int_keyed_map.insert(std::make_pair(s2, s2.GetName()));
    std::cout << "String based keys: object order" << std::endl;
    print_seq(int_keyed_map);
    return 0;
}

Leaving aside from the legality of this and any possible semantic misunderstandings, addressed already, I cannot think of any reason to use std::map here rather than std::unordered_map . 除了已经解决的合法性和可能的​​语义误解之外,我想不出任何理由在这里使用std::map而不是std::unordered_map There are early intercepts of this in Boost and Visual C++ if you are on a pre-C++11 compiler. 如果您使用的是C ++ 11之前的编译器,则Boost和Visual C ++中会对此进行早期拦截。

Since you appear to be using a pointer to represent a unique object, something like boost::flyweight could be applicable. 由于您似乎正在使用指针来表示唯一对象,因此可以使用boost :: flyweight之类的东西。

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

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