f1m*_*sch 2 c++ stdmap emplace c++17
首先在 c++17 中,我有一个类似的结构
typedef struct ST_A{
int a;
string s;
ST_A(const int a, const string&s) :a(a),s(s) {}
}st_A;
Run Code Online (Sandbox Code Playgroud)
现在我有一个简单的地图,并根据 cppreference放置了两次
map<string, st_A> m1;
m1.emplace("c", 10, "c"); ---> case 1
m1.emplace(std::piecewise_construct, ---> case 2
std::forward_as_tuple("c"),
std::forward_as_tuple(10, "c"));
Run Code Online (Sandbox Code Playgroud)
情况 2 工作正常,但情况 1 编译错误。那么情况1如何解决并emplace尽可能简洁呢?
如果情况map更复杂怎么办?比如
map<string, deque<pair<int, st_A>>> m2,如何尽可能emplace简洁?
如果自定义结构体有更多构造函数怎么办?比如
typedef struct ST_A{
int a = 0;
string s;
ST_A(const int a) :a(a) {}
ST_A(const string&s) :s(s) {}
ST_A(const int a, const string&s) :a(a),s(s) {}
}st_A;
Run Code Online (Sandbox Code Playgroud)
如果实际上有一些合理的方法来emplace作为 cppreference 中的上述链接,它会让编译器感到困惑吗?
UPDATE
如果我原来的地图是map<string, deque<pair<int, st_A>>> m2,现在我想添加一个元素 。pair{"c1", pair{1, st_A{10, "c"}}}也就是说,添加后,m2 变成代码map{{"c1",deque{pair{1,st_A{10, "c"}}}}
形式insert就像
m2.insert({"c1", {{1, {10, "c"}}}});
Run Code Online (Sandbox Code Playgroud)
但它可能会调用太多的ctor/copy ctor,如果我想在性能上以更高效的方式编写,怎么可能呢?
emplace()std::pair<const Key,Value>从传递的参数构造。
如果没有std::piecewise_construct,您必须传递两个参数,一个用于构造键,一个用于构造值:
m1.emplace("c", st_A{10, "c"});
Run Code Online (Sandbox Code Playgroud)
这违背了“安置”的目的,因为您是在调用之前构建值。
我的建议是使用try_emplace具有更友好 API 的 API,特别是如果密钥很简单并且完全允许您想要的内容:
auto [it, inserted ] = m1.try_emplace(Key{key_args...}, value_args...);
Run Code Online (Sandbox Code Playgroud)
auto [it, inserted ] = m1.try_emplace("c", 10, "c");
Run Code Online (Sandbox Code Playgroud)
一般来说,第一个参数构造键,其余参数构造值。Key因此,如果 ctor 只接受一个参数,则可以省略。
返回值指示该元素是否已经存在inserted或者是否已经存在具有相同键的元素。it基本都回来了m1.at("c")。
键总是被构造的,值参数仅在 if 时被“消耗”(=移出)inserted==true。否则它们就不会受到影响。
对于map<string, deque<pair<int, st_A>>> m2;,您可以执行以下操作:
m2["C"].emplace_back(1, st_A{10, "c"});
Run Code Online (Sandbox Code Playgroud)
std::deque没有接受单个元素的构造函数,聚合初始化也不起作用。并不是说它会保存任何副本,std::deque::emplace_back已经实现了这一点。m2["C"]施工效率也已经如此。
如果您还想st_A暂时删除,您可以再次回退到std::pairs std::piecewise_construct:
m2["C"].emplace_back(std::piecewise_construct, std::forward_as_tuple(1),
std::forward_as_tuple(10, "c"));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
142 次 |
| 最近记录: |