繁体   English   中英

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

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

我有一个问题,当在映射中用作键时如何处理指向自定义对象的指针。 更具体地说,如果我定义

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

默认的C ++实现是否可以处理这些指针? 还是我需要定义一个自定义比较器函数来处理它? 通常,将对象的指针用作键是否是一种好习惯?

默认实现将比较指针存储的地址,因此不同的对象将被视为不同的键。 但是,将不考虑对象的逻辑状态。 例如,如果您使用std::string *作为键,则具有相同文本"Hello"两个不同的std::string对象将被视为不同的键! (按地址存储在地图中)

只要您了解上述重要区别,就可以将指针用作键。

将处理指针,但将其作为指针进行比较(内存顺序)。 如果要比较对象,则必须通过自定义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专业化,因此可以安全地将它们用作映射键等。

指针可以用作键,但是特别是在std :: map(或std :: set)中,我不建议这样做。 程序的行为不是确定性的,即,当在地图上进行迭代时,不能保证迭代地图中的项目的顺序是相同的 它实际上取决于对象(键)的内存地址。 看一下这个示例,您可以看到,无论键在映射中的插入顺序如何,当键是字符串而不是指针时,都以确定性方式迭代项目。

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

除了已经解决的合法性和可能的​​语义误解之外,我想不出任何理由在这里使用std::map而不是std::unordered_map 如果您使用的是C ++ 11之前的编译器,则Boost和Visual C ++中会对此进行早期拦截。

由于您似乎正在使用指针来表示唯一对象,因此可以使用boost :: flyweight之类的东西。

暂无
暂无

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

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