4

私は C++ と STL の専門家ではありません。

Map 内の構造をデータとして使用します。キーはクラスC1です。同じデータにアクセスしたいのですが、別のキー C2 も使用します (C1 と C2 は無関係な 2 つのクラスです)。

これは、データを複製せずに可能ですか? グーグルで検索してみましたが、理解できる答えを見つけるのに苦労しました。

これは、boost ライブラリがサポートされていない組み込みターゲット用です。

誰か助けてくれませんか?

4

7 に答える 7

4

へのポインターを値Dataとして格納するstd::mapことができ、同じデータを指す異なるキーを持つ 2 つのマップを持つことができます。

このようなデータの共有所有権の場合、次のようなスマートポインターstd::shared_ptrが適切なオプションだと思います。

#include <map>       // for std::map
#include <memory>    // for std::shared_ptr

....

std::map<C1, std::shared_ptr<Data>> map1;
std::map<C2, std::shared_ptr<Data>> map2;

のインスタンスは、Dataを使用して割り当てることができますstd::make_shared()

于 2013-07-16T10:19:16.980 に答える
3

標準ライブラリにはありませんが、Boost は提供していますboost::multi_index

于 2013-07-16T10:11:22.263 に答える
3

異なるタイプの 2 つのキー

私は少し読み違えていたことを認めなければなりません。値ではなく、異なるタイプの 2 つのキーが必要であることに実際には気付きませんでした。ただし、その解決策は以下の内容に基づいています。他の答えには、そのために必要なものがほとんどあります。ユニバーサルルックアップ関数を作成できることを付け加えておきます:(C++ 14っぽい疑似コード)。

template<class Key> 
auto lookup (Key const& key) { }

そして、それをあなたの鍵に特化させます (おそらく SFINAE よりも簡単です)

template<>
auto lookup<KeyA> (KeyA const& key) { return map_of_keys_a[key]; }

についても同様ですKeyB

それをクラスにカプセル化したい場合は、 に変更lookupするのが当然の選択operator[]です。


タイプは同じだが値が異なるキー

アイデア1

私が 60 秒で思いつく最も簡単な解決策: (最も単純な意味は、それが本当に熟考されるべきであることを意味します)。また、デフォルトとして切り替えunordered_mapます。

map<Key, Data> data;
map<Key2, Key> keys;

経由でアクセスしdata[keys["multikey"]]ます。

これは明らかにいくらかのスペースを無駄にします (Keyタイプのオブジェクトを複製します) が、それらはタイプよりもはるかに小さいと想定していますData

アイデア2

別の解決策は、ポインターを使用することです。重複の唯一のコストは(スマート)ポインターです。

map<Key, shared_ptr<Data>> data;

のオブジェクトはData、それを指すキーが少なくとも 1 つある限り存続します。

于 2013-07-16T10:11:34.393 に答える
2

これらの場合に私が通常行うことは、所有されていないポインターを使用することです。データをベクターに保存します。

std::vector<Data> myData;

次に、ポインターを各要素にマップします。ただし、ベクトルの将来の成長のためにポインターが無効になる可能性があるため、この場合はベクトル インデックスを使用することを選択します。

std::map<Key1, int> myMap1;
std::map<Key2, int> myMap2;

データ コンテナーをクライアントに公開しないでください。要素の挿入と削除を特定の関数にカプセル化して、どこにでも挿入し、どこにでも削除します。

于 2013-07-16T10:15:03.233 に答える
1

すべてのデータをプレーンにstd::list保持し、std::map任意のキー値をリストを指すイテレータにマッピングするさまざまなオブジェクトを検討できます。

std::list<Data> values;
std::map<C1, std::list<Data>::iterator> byC1;
std::map<C2, std::list<Data>::iterator> byC2;

つまり、多かれ少なかれ生のポインターをいじる代わりに、プレーンなイテレーターを使用します。また、 a へのイテレータには、std::list非常に優れた無効化保証があります。

于 2013-07-16T10:23:51.277 に答える
0

私は同じ問題を抱えていました。最初は、共有ポインター用に2つのマップを保持するのは非常にクールに聞こえました。ただし、この 2 つのマップを管理する必要があります (挿入、削除など)。

これを行う他の方法を思いついたよりも。私の理由は次のとおりです。xy または radius-angle でデータにアクセスします。各ポイントはデータを保持すると考えてください。ただし、ポイントはデカルト x,y または radius-angle として記述できます。

だから私は次のような構造体を書きました

struct MyPoint
{
    std::pair<int, int> cartesianPoint;
    std::pair<int, int> radianPoint;

    bool operator== (const MyPoint& rhs)
    {
         if (cartesianPoint == rhs.cartesianPoint || radianPoint == rhs.radianPoint)
             return true;
         return false;
    }
}

その後、それをキーとして使用できましたが、

std::unordered_map<MyPoint, DataType> myMultIndexMap;  

あなたのケースが同じか、このシーンに合わせて調整できるかどうかはわかりませんが、オプションになる可能性があります.

于 2015-01-03T13:46:35.547 に答える