7

std::map<std::string, T>(またはunordered_map) があり、イテレータ/参照/ポインタからコンテンツへのキーにアクセスしたいとします。

std::stringキーの 2 つのコピー (1 つはマップが所有し、もう 1 つはコンテンツ オブジェクト内)を持たずにそれを行う方法はありますか? 一方が他方への参照になることはできますか?

4

4 に答える 4

3

boost::bimap の使用を検討しますか? 以下に簡単な例を示します。

#include <boost/bimap.hpp>
#include <string>
struct Person
{
    Person()
    {}
    Person(const std::string& f, const std::string& l, int a) : first(f), last(l), age(a)
    {}
    std::string first;
    std::string last;
    int age;
};

bool operator <(const Person& lhs, const Person& rhs)
{
    if(lhs.last < rhs.last)
        return true;
    return false;
}

std::ostream& operator << (std::ostream& os, const Person& p)
{
    os << "First Name: " << p.first << " Last Name: " << p.last << " Age: " << p.age;
    return os;
}

int main() 
{
    typedef boost::bimap<std::string, Person> people;
    typedef people::value_type value;

    people m;
    m.insert(value("12345",Person("fred", "rabbit", 10)));
    m.insert(value("67890",Person("benjamin", "bunny", 12)));

    Person p = m.left.at("12345");
    std::cout << "Person with serial no. 12345 is: " << p << "\n";
    std::cout << "Serial number of " << p << " is: " << m.right.at(p) << "\n";

}
于 2013-08-28T19:51:32.317 に答える
2

彼らがこれを難しくした理由は、危険だからです。std::stringキーオフされているメンバーの値が決して変更されないこと、またはマップ全体が無効になることを保証する必要があります。興味深いことに、頭に浮かぶ最初のソリューションは非常にハックに見え、UB のように見えますが、私は非常に慎重に UB を回避していると思います。

struct key_type {
    mutable const char* ptr;    
};
bool operator<(const key_type& lhs, const key_type& rhs)
{return strcmp(lhs.ptr, rhs.ptr)<0;}

struct person {
    std::string name;
    int age;
};
person& people_map_get(std::map<key_type, person>& map, const char* name) {
    auto it = map.insert(name, person{name}).first; //grab, possibly insert
    if->first.ptr = it->second.name.c_str(); //in case of insert, fix ptr
    return it->second;
}
person& people_map_assign(std::map<key_type, person>& map, person p) {
    auto pair = map.insert(name, p); //grab, possibly insert
    auto it = pair.first;       
    if (pair.second == false) 
        it->second = std::move(p);
    if->first.ptr = it->second.name.c_str(); //ptr probably invalidated, so update it
    return it->second;
}

int main() {
    std::map<key_type, person> people;
    people_map_assign(people, person{"ted"});
    person frank = people_map_get(people, "frank");
}

が明確に願っているように、これはUB に非常に近いものであり、あまりお勧めできません。基本的に、挿入/検索中、キーは一時オブジェクトまたは入力文字列を指し、オブジェクトが挿入/検索されるとすぐに、キーは文字列メンバーに含まれる値を指すように変更されます。.c_str()含まれているpersonオブジェクトの戻り値を無効にするようなことは決してしないでください。すべてがほとんど機能しません。おもう。

于 2013-08-28T20:12:51.223 に答える
1

2 つのオブジェクトを作成してみませんか。

std::set<std::string> wordSet;
std::map<std::string*, T> yourMap;

T には std::string へのポインターが含まれている必要があり、yourMap にはカスタム コンパレーターが必要です。さらに、これらすべてをいくつかのクラスにラップできます。

于 2013-08-28T19:41:09.127 に答える
-1

どちらも同じ値を参照できます。例えば:

#include <stdio.h>
#include <string>
#include <map>

struct xx { std::string mykey; int value; };

int main (int argc, char **argv)
{
    std::string                     key1("the-key");
    std::map<std::string, xx>       map;

    map[key1].mykey = key1;
    map[key1].value = 13;

    std::string &lookup_key = map[key1].mykey;

    printf("%d\n", map[lookup_key].value);
}
于 2013-08-28T19:10:02.230 に答える