如何使用std::map::emplace添加不可移动类型的默认构造值
C++ std::map中仅传键默认构造值的方法
可编译代码示例
#include <map> struct S { int val = 0; S() = default; S(S&&) = default; }; int main() { std::map<int, S> values; values.emplace(42, S{}); }
这段代码能正常编译,因为S的移动构造函数可用,emplace可以将临时创建的S对象移动到std::pair的第二个成员中。
不可编译代码示例
#include <map> struct S { int val = 0; S() = default; S(S&&) = delete; }; class Wrapper { public: std::map<int, S> values; void AddEmptyValue(int key, int) { values.emplace(key, S{}); } };
这段代码无法编译,原因很明确:我们创建了S的右值,但S的移动构造函数被删除,无法将这个右值移动到std::pair的第二个成员中。
解决方法:仅传键让值默认构造
要实现只传入键,就让对应的值在std::map内部默认构造,避免移动/拷贝操作,有几种可行的方式:
方式1:使用std::piecewise_construct(兼容C++11及以上)
通过std::piecewise_construct配合std::forward_as_tuple,分别传递键的构造参数和值的构造参数(值不需要参数,传递空tuple即可),这样std::pair会分别构造键和值,值会被默认构造:
#include <map> #include <tuple> struct S { int val = 0; S() = default; S(S&&) = delete; }; class Wrapper { public: std::map<int, S> values; void AddEmptyValue(int key, int) { values.emplace(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple()); } };
方式2:直接传递键参数(兼容C++11及以上)
std::map::emplace可以接受用来构造std::pair<const Key, T>的参数,当仅传递键时,std::pair会用该键构造第一个成员,同时默认构造第二个成员(只要T可默认构造):
#include <map> struct S { int val = 0; S() = default; S(S&&) = delete; }; class Wrapper { public: std::map<int, S> values; void AddEmptyValue(int key, int) { values.emplace(key); } };
方式3:使用try_emplace(C++17及以上)
如果需要确保仅当键不存在时才插入新值,可以用try_emplace,同样仅传递键即可让值默认构造:
#include <map> struct S { int val = 0; S() = default; S(S&&) = delete; }; class Wrapper { public: std::map<int, S> values; void AddEmptyValue(int key, int) { values.try_emplace(key); } };
内容的提问来源于stack exchange,提问作者Oersted
相关产品推荐
相关产品推荐

