提问人:Doot 提问时间:10/21/2020 更新时间:10/21/2020 访问量:471
C++:如何将键和值传递到构造函数中以制作映射,而无需在构造过程中复制映射的值?
C++: How can I pass keys and values into a constructor to make a map without copying the values of the map during construction?
问:
下面是一个最小示例,其中类型的对象包含 .地图中唯一会改变的是值,而不是长度,也不是键。WrapMap
unordered_map
但是,我发现传递给每对的每个值都会被复制两次。
通过使用 ,它似乎将副本数减少了 1(尽管该移动没有显示在输出中,所以也许我做错了什么)。move
#include <iostream>
#include <unordered_map>
using std::cout;
struct MyStruct {
int x;
MyStruct(int x) : x(x) { cout << "Constructed " << this << " from " << x << "\n"; }
MyStruct(const MyStruct& from) : x(from.x) { cout << "Copied " << this << " from " << &from << "\n"; }
MyStruct(MyStruct&& from) : x(from.x) { cout << "Moved " << this << " from " << &from << "\n"; }
~MyStruct() { cout << "Destructed " << this << " from " << x << "\n"; }
};
struct WrapMap {
std::unordered_map<std::string, MyStruct>&& my_map;
WrapMap(std::unordered_map<std::string, MyStruct>&& kv)
: my_map(std::move(kv)) {
/*
// Just to make sure it inputs the values correctly
cout << "{";
for (auto it = my_map.begin(); it != my_map.end(); ++it) {
if (it != my_map.begin()) cout << ", ";
cout << it->first << ": MyStruct " << it->second.x;
}
cout << "}\n";
*/
}
};
int main() {
WrapMap object({
{"foo", 2},
// several pairs
});
}
Constructed 0x7ffd76fadbb8 from 2
Copied 0x2611c80 from 0x7ffd76fadbb8
{foo: MyStruct 2}
Destructed 0x7ffd76fadbb8 from 2
Destructed 0x2611c80 from 2
我的假设是长指针指向常量内存(只是一个猜测),因此它必须将每个元素从常量内存复制到非常量内存。
我尝试使用 an 但无法将其转换为 .initializer_list<pair<string, MyStruct>>
unordered_map
std::unordered_map<std::string, MyStruct> object = { {"foo", 2} }
似乎为每个值调用复制构造函数。
我怎样才能使每个密钥永远不会被复制(或至少最小化它?
相关新闻: 插入无序地图调用构造函数
答:
EMPLACE公司
您可以使用以下的 emplace
成员函数:unordered_map
如果容器中没有具有键的元素,则将新元素插入到使用给定参数就地构造的容器中。
谨慎使用 emplace 可以构造新元素,同时避免不必要的复制或移动操作。新元素(即 )的构造函数被调用,其参数与提供给 emplace 的参数完全相同,通过 转发。[...]
std::pair<const Key, T>
std::forward<Args>(args)...
std::unordered_map<std::string, MyStruct> m;
m.emplace(std::make_pair("foo", 2));
C++17:try_emplace
从 C++17 开始,您还可以使用try_emplace
,如果密钥已存在,则允许保留传递给它的给定资源:
[...]与 or 不同,如果不发生插入,这些函数不会从右值参数中移动,这使得操作值为仅移动类型的映射变得容易,例如 。此外,将键和参数分别处理mapped_type,这与需要参数来构造 a (即 a ) [...] 不同。
insert
emplace
std::unordered_map<std::string, std::unique_ptr<foo>>
try_emplace
emplace,
value_type
std::pair
std::unordered_map<std::string, MyStruct> m;
m.try_emplace("foo", 2);
评论