C++ 将对映射元素的引用作为参数传递

C++ 将对映射元素的引用作为参数传递,c++,oop,unordered-map,C++,Oop,Unordered Map,我有两门课: class Container { /* ... */ // Type 'PersonDetails' is a struct. std::unordered_map<unsigned int, PersonDetails> AllDetails; }; 并不是说类容器动态地更改所有细节的内容。在我的main函数中,我构造了一个Container的对象和很多Person。每个Person对象都有一个唯一的id(它是AllDetails的键),

我有两门课:

class Container
{
    /* ... */

    // Type 'PersonDetails' is a struct.
    std::unordered_map<unsigned int, PersonDetails> AllDetails;
};
并不是说类
容器
动态地更改
所有细节的内容。在我的
main
函数中,我构造了一个
Container
的对象和很多
Person
。每个
Person
对象都有一个唯一的id(它是
AllDetails
的键),但我不想将它作为参数传递给
Person
的构造函数。相反,我希望将一个直接引用传递给地图的元素,该元素将一直有效

我曾想过传递迭代器,但在更新期间或向
AllDetails
添加映射时,迭代器很可能会失效

我该怎么做呢?

试试这个:

#include <map>
#include <vector>
#include <memory>
#include <string>
#include <cassert>

struct PersonDetails 
{
    PersonDetails()
        : Age(0)
    {}

    std::string Name;
    int Age;
};

class Container
{
    /* ... */
public:
    typedef std::map<unsigned int, PersonDetails> PersonDetailsMap;
    typedef PersonDetailsMap::value_type          PersonDetailsElement;

    PersonDetailsElement& GetDetails(unsigned int ID)
    {
        auto it = AllDetails.lower_bound(ID);
        if (it != AllDetails.end() && !AllDetails.key_comp()(ID, it->first))
            return *it;
        else
            return *AllDetails.insert(it, std::make_pair(ID, PersonDetails()));
    }

    // Type 'PersonDetails' is a struct.
    std::map<unsigned int, PersonDetails> AllDetails;
};

class Person
{
public:

    Container::PersonDetailsElement& Details;

    Person(Container::PersonDetailsElement& details)
        : Details(details)
    {}
};

int main()
{
    Container c;

    using namespace std;
    vector<shared_ptr<Person>> people;

    for (int i = 0; i < 10000; ++i)
    {
        people.push_back(make_shared<Person>(c.GetDetails(i)));
        people.back()->Details.second.Age = 10 + i;
        people.back()->Details.second.Name = string("Bob");

        assert(people.back()->Details.first == i);
        assert(c.AllDetails[i].Age == 10 + i);
        assert(c.AllDetails[i].Name == string("Bob"));
    }
}
#包括
#包括
#包括
#包括
#包括
结构个性化
{
个人信息()
:年龄(0)
{}
std::字符串名;
智力年龄;
};
类容器
{
/* ... */
公众:
typedef std::map PersonDetailsMap;
typedef PersonDetailsMap::value_type PersonDetailsElement;
PersonDetailsElement和GetDetails(未签名的整数ID)
{
自动it=所有详细信息。下限(ID);
if(it!=AllDetails.end()&&!AllDetails.key_comp()(ID,it->first))
归还它;
其他的
return*AllDetails.insert(it,std::make_pair(ID,PersonDetails());
}
//类型“PersonDetails”是一个结构。
std::映射所有细节;
};
班主任
{
公众:
集装箱:个人定制和详细信息;
人员(容器::人员详细信息)
:详情
{}
};
int main()
{
容器c;
使用名称空间std;
媒介人;
对于(int i=0;i<10000;++i)
{
人。推回(使你共享(c.GetDetails(i));
people.back()->Details.second.Age=10+i;
people.back()->Details.second.Name=string(“Bob”);
断言(people.back()->Details.first==i);
断言(c.AllDetails[i].Age==10+i);
assert(c.AllDetails[i].Name==string(“Bob”);
}
}

你能用(伪)代码说明你在寻找什么吗?它非常不清楚。为什么不想将唯一ID传递给
人员
构造函数?对我来说,这似乎是最好的方法。迭代器可以失效的原因是,映射可以自行重新排列内存,而不管您如何捕获引用,这都是正确的。这并不是因为迭代器的设计者想让你的生活更艰难——它可以改变,因为这是处理地图的功能性要求。你可以随意传递地址,但地图仍然可以在你背后移动对象。我同意,您实际上应该只存储ID并根据需要进行查找。如果您想要稳定的迭代器,请使用基于节点的类,例如
std::map
。此外,
unordered_map
的插入可以使迭代器无效,但不能使元素的引用(和指针)无效,因此如果需要,您还可以直接存储指针。
#include <map>
#include <vector>
#include <memory>
#include <string>
#include <cassert>

struct PersonDetails 
{
    PersonDetails()
        : Age(0)
    {}

    std::string Name;
    int Age;
};

class Container
{
    /* ... */
public:
    typedef std::map<unsigned int, PersonDetails> PersonDetailsMap;
    typedef PersonDetailsMap::value_type          PersonDetailsElement;

    PersonDetailsElement& GetDetails(unsigned int ID)
    {
        auto it = AllDetails.lower_bound(ID);
        if (it != AllDetails.end() && !AllDetails.key_comp()(ID, it->first))
            return *it;
        else
            return *AllDetails.insert(it, std::make_pair(ID, PersonDetails()));
    }

    // Type 'PersonDetails' is a struct.
    std::map<unsigned int, PersonDetails> AllDetails;
};

class Person
{
public:

    Container::PersonDetailsElement& Details;

    Person(Container::PersonDetailsElement& details)
        : Details(details)
    {}
};

int main()
{
    Container c;

    using namespace std;
    vector<shared_ptr<Person>> people;

    for (int i = 0; i < 10000; ++i)
    {
        people.push_back(make_shared<Person>(c.GetDetails(i)));
        people.back()->Details.second.Age = 10 + i;
        people.back()->Details.second.Name = string("Bob");

        assert(people.back()->Details.first == i);
        assert(c.AllDetails[i].Age == 10 + i);
        assert(c.AllDetails[i].Name == string("Bob"));
    }
}