「这是我参与11月更文挑战的第 10 天,活动详情查看:2021最后一次更文挑战」。
参加该活动的第 22 篇文章
前文 C++11 中的 emplace 存在的意义与注意事项 中提到过 map 在使用 emplace
的时候需要注意一点,现在让我们回顾一下:
值得注意的是
map
类型的emplace
处理比较特殊,因为和其他的容器不同,map
的emplace
方法把它接收到的所有的参数都一起转发给pair
的构造函数。但是对于一个pair
来说,它既需要构造它的key
又需要构造它的value
。如果我们按照之前普通的语法使用变参模板的话,则它是无法区分哪些参数用来构造key
, 哪些用来构造value
的。 比如下面的代码
// @note 无法区分哪个参数用来构造 key 哪些用来构造 value // 有可能是 std::string s("hello", 1), std::complex<double> cpx(2) // 也有可能是 std::string s("hello"), std::complex<double> cpx(1, 2) std::map<std::string, std::complex<double>> scp; scp.emplace("hello", 1, 2);
那我们该如何解决以上的这个问题呢? 首先,我们想到的是可以接受异构、变长参数的 tuple
来对参数进行分组。
我们将代码改成如下形式
std::pair<std::string, std::complex<double>> scp(
std::make_tuple("hello"),
std::make_tuple(1, 2));
可是这种语法还是编译无法通过。
这是因为这里还是有问题,两个 tuple
找不到正确的构造函数。
这个时候就需要使用 C++11 为我们提供的一个特殊类型 piecewise_construct_t
来帮助它们找到各自正确的构造函数了。
std::piecewise_construct_t
是一个空类,全局变量std::piecewise_construct
就是该类型的一个变量。
则代码可以修改为如下
std::pair<std::string, std::complex<double>> scp(
std::piecewise_construct,
std::make_tuple("hello"),
std::make_tuple(1, 2));
std::piecewise_construct
—— 此常量值作为构造 pair 对象的第一个参数传递,以选择构造函数形式,通过将两个元组对象的元素转发给它们各自的构造函数来构造其成员。
调试结果如下
可见,这两个元组已经分别存在了 pair
的 first
和 second
的位置了【即第一个 tuple 作为 key,第二个 tuple 作为 value】
然后我们回到 map
中的 emplace
操作
因为 emplace
会把参数完美转发给 pair
进行构造,所以保证一致性,你需要使用同样的语法来完成 emplace
的调用,使用 forward_as_tuple
替代 make_tuple
,该函数会帮你构造一个 tuple
并转发给 pair
。
具体代码如下所示
std::map<std::string, std::complex<double>> scp;
scp.emplace(std::piecewise_construct, ///< 此常量值作为构造 pair 对象的第一个参数传递,以选择构造函数形式,通过将两个元组对象的元素转发给它们各自的构造函数来构造其成员。
std::forward_as_tuple("hello"), ///< 该函数会帮你构造一个 tuple 并转发给 pair 构造,并存储在 first 字段
std::forward_as_tuple(1, 2)); ///< 该函数会帮你构造一个 tuple 并转发给 pair 构造,存储在 second 字段
std::cout << scp["hello"] << std::endl;
所以,想对于 map
避免临时变量的构造的话,你就需要构建两个 tuple
【增加了很多麻烦的步骤】。 至于这些操作是否值得,需要代码编写者自己考虑,从性能和代码优雅性、可读性上进行权衡。
所以,个人认为对于临时变量构建代价不是很大的对象(比如基础类型)建议使用 insert
而不是 emplace
,毕竟写法简介、通俗易懂。
scp.insert({"world", {1, 2}});
今天的文章C++11 中 std::piecewise_construct 的使用分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/22982.html