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"));
}
}