我有一个map
类型的<int, foo*>
,我正在从数据库中填充。 int
是唯一键,因此在填充之前,我要检查是否在地图中已经创建了键foo
并将其插入地图中。
foo
类还具有另一个类型为<int, float>
的映射作为属性,也需要从数据库中填充。我有下面的代码,据说很简单:
std::map<int, foo> MAP;
while(getline(infile, line))
{ //reading records in data file
string item;
stringstream ss(line);
vector<string> splittedString;
int a = stoi(splittedString[0]); // cells after splitting data
int b = stoi(splittedString[1]);
float c = stof(splittedString[2]);
if (MAP.find(a) == MAP.end())
{
foo f = foo();
MAP.insert({a, &f});
f.fooMap.insert({b, c/100});
}
else
{
foo* f = MAP.at(a);
f->fooMap.insert({b, c/100});
}
}
这花了很多时间来计算。大约有50,000条记录,但这不会永远保留。我很确定自己做错了,因为我对c ++有点生疏。
我知道创建foo对象时存在一些冗余,并且我认为执行上述操作的更有效方法是以下“错误”代码:
while(getline(infile, line))
{//reading records in data file
string item;
stringstream ss(line);
vector<string> splittedString;
int a = stoi(splittedString[0]); //cells after splitting data
int b = stoi(splittedString[1]);
float c = stof(splittedString[2]);
foo f = *MAP[a];
if (f == NULL)
{
f = foo();
MAP.insert({a, &f});
}
f->fooMap.insert({b, c/100});
}
如果我使用MAP<int, foo>
而不是MAP<int, foo*>
(并相应地安排了插入代码),则该代码可以正常工作。所以我在用指针做错了。解决此问题的最佳方法是什么?
答案 0 :(得分:0)
您的代码要复杂得多。您应该让std::map
进行工作,而不要自己尝试。您需要的是容器的.emplace
函数。它不仅跳过了不必要的插入操作,而且还为您提供了正确的修改条目。例如,您可以执行以下操作:
#include <iostream>
#include <map>
#include <string>
int main()
{
//helper
auto print = [](auto MAP)
{
std::cout << "MAP:\n";
for (auto && each : MAP)
std::cout << each.first << "->" << each.second << '\n';
};
//work
std::map<int, std::string> MAP;
MAP.emplace(1,"").first->second = "one";
MAP.emplace(2,"").first->second = "two";
print(MAP);
MAP.emplace(1,"").first->second = "three";
print(MAP);
}
哪个会产生以下输出:
MAP:
1->one
2->two
MAP:
1->three
2->two
当然,这具有奇怪的.first->second
语法,但是我们可以将其重构为新的lambda:
auto update = [](auto& MAP, auto index, auto entry)
{
MAP.emplace(index,"").first->second = entry;
};
可让您编写以下内容:
update(MAP, 1, "one");
update(MAP, 2, "two");
print(MAP);
update(MAP, 1, "three");
print(MAP);
编辑
因为您要求的是std::unique_ptr
解决方案,所以就这样:
#include <iostream>
#include <map>
#include <string>
#include <memory>
int main()
{
//helper
auto print = [](const auto& MAP)
{
std::cout << "MAP:\n";
for (auto && each : MAP)
std::cout << each.first << "->" << *each.second.get() << '\n';
};
//work
std::map<int, std::unique_ptr<std::string>> MAP;
auto update = [](auto& MAP, auto index, auto entry)
{
*MAP.emplace(index, std::make_unique<std::string>()).first->second.get() = entry;
};
update(MAP, 1, "one");
update(MAP, 2, "two");
print(MAP);
update(MAP, 1, "three");
print(MAP);
}
不幸的是,由于std::unique_ptr
无法复制,因此有点难以理解。 (这只是它的实现方式。)