簡體   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