簡體   English   中英

如何制作一個 C++ 映射容器,其中鍵是值的一部分?

[英]How to make a C++ map container where the key is part of the value?

我想存儲一堆鍵值對象,但是值對象本身(和對它的引用)知道它的鍵。 我還想有效地查找僅給定鍵的這些對象。

class SomeObject
{
private:
    //String or integer. int seem cheap enough to duplicate with std::map, but
    //strings seem pretty expensive when there may be thousands of objects in existence.
    //Reference/Pointer to key is fine
    const SomeOtherObject key;
    ...other stuff...
public:
    ...methods, some of which use the key in some way...
};
  • 標准::地圖
    • 似乎要求存儲是 std::pair,這樣值就不能訪問密鑰。 如果值包含鍵,則需要復制它。
    • 實際上並不強制值中的鍵不會以某種方式改變
  • 標准::設置
    • 看起來是一個非常好的解決方案,使用自定義比較方法按鍵提供唯一性,直到您意識到它使您的整個值成為常量,而不僅僅是鍵字段。
  • std::vector (或其他類似數組/列表的解決方案)
    • 可以使用線性搜索,或者如果項目保持排序,則進行二分搜索。 但是,我懷疑這在性能方面並不是最佳的,並且需要某種額外的層來真正實現所需的行為。

C++14 std::set::find非鍵搜索

http://en.cppreference.com/w/cpp/container/set/find所述,C++14 添加了兩個新的find API:

主程序

template< class K > iterator find( const K& x );
template< class K > const_iterator find( const K& x ) const;

這允許您執行以下操作:

主程序

#include <cassert>
#include <set>

class Point {
    public:
        // Note that there is _no_ conversion constructor,
        // everything is done at the template level without
        // intermediate object creation.
        //Point(int x) : x(x) {}
        Point(int x, int y) : x(x), y(y) {}
        int x;
        int y;
};
bool operator<(const Point& c, int x) { return c.x < x; }
bool operator<(int x, const Point& c) { return x < c.x; }
bool operator<(const Point& c, const Point& d) {
    return c.x < d;
}

int main() {
    // std::less<> because of:
    // https://stackoverflow.com/questions/20317413/what-are-transparent-comparators
    std::set<Point, std::less<>> s;
    s.insert(Point(1, -1));
    s.insert(Point(2, -2));
    s.insert(Point(0,  0));
    s.insert(Point(3, -3));
    assert(s.find(0)->y ==  0);
    assert(s.find(1)->y == -1);
    assert(s.find(2)->y == -2);
    assert(s.find(3)->y == -3);
    // Ignore 1234, find 1.
    assert(s.find(Point(1, 1234))->y == -1);
}

在 Ubuntu 16.10、 g++ 6.2.0 上測試,使用:

g++ -std=c++14 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out

使用自定義類而不是less<>

這使事情更加明確,並允許您為每個類編寫多個比較器:

#include <cassert>
#include <set>

class Point {
    public:
        Point(int x, int y) : x(x), y(y) {}
        int x;
        int y;
};

struct PointCmpY {
    // https://stackoverflow.com/questions/20317413/what-are-transparent-comparators
    typedef std::true_type is_transparent;
    bool operator()(const Point& lhs, int rhs) const {
        return lhs.y < rhs;
    }
    bool operator()(int lhs, const Point& rhs) const {
        return lhs < rhs.y;
    }
    bool operator()(const Point& lhs, const Point& rhs) const {
        return lhs.y < rhs.y;
    }
};

int main() {
    std::set<Point, PointCmpY> s;
    s.insert(Point(1, -1));
    s.insert(Point(2, -2));
    s.insert(Point(0,  0));
    s.insert(Point(3, -3));
    assert(s.find(0)->x == 0);
    assert(s.find(-1)->x == 1);
    assert(s.find(-2)->x == 2);
    assert(s.find(-3)->x == 3);
    assert(s.find(Point(1234, -1))->x == 1);
}

也可以看看

我感覺到你的痛苦。 讓我生氣的是setmap總是使用相同的數據結構在引擎蓋下實現,這是一個用鍵提取器參數化的值tree 不幸的是,標准中沒有這樣的東西。

如果 boost 沒問題,請使用Boost.MultiIndex來實現您的需求。 也看看Boost.Intrusive

C++ 提供了mutable關鍵字,允許您使用第二種解決方案—— set 在您的項目類中將您的值聲明為mutable將允許修改它,即使該項目是const 另請參閱:除了允許 const 函數修改變量之外,“mutable”關鍵字還有其他用途嗎?

或者,更簡單的是,為您的值實現一個訪問器, const_cast遠離項目的常量性。

...但是值對象本身(和對它的引用)知道它的鍵

地圖:

對象無法知道“它的”鍵,因為指向同一個對象的指針可能會被添加到多個映射中,使用不同的鍵。 密鑰屬於地圖; 不是對象。

放:

當這個成員的值發生變化時會發生什么? 您將如何強制重新索引? 這就是 set 強制執行常量的原因。

——

您正在嘗試根據其成員之一對給定類的項目進行索引,但您不想復制此成員用於索引目的,並且您不想使對象成為 const(我假設您確實想要使成員為 const)。

我會在紅黑樹或 AVL 樹上構建它。

我對 ybungalobill 建議的 Boost.MultiIndex 不夠熟悉。 我不確定它的實例化代碼是否復制了索引成員,或者它如何處理該成員的值更改。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM