c – 作为参数传递正在移动的对象的成员是否安全

c – 作为参数传递正在移动的对象的成员是否安全,第1张

概述#include <iostream>#include <string>#include <map>struct A { int n { 42 }; std::string s { "ciao" };};int main() { A a; std::map<std::string, A> m; std::cout << "a.s: " << a
#include <iostream>#include <string>#include <map>struct A {    int n { 42 };    std::string s { "Ciao" };};int main() {    A a;    std::map<std::string,A> m;    std::cout << "a.s: " << a.s << std::endl; // print: "a.s: Ciao"    m.emplace(a.s,std::move(a)); // a.s is a member of a,moved in the same line    std::cout << "in map: " << m.count("Ciao") << std::endl; // print: "in map: 1"    std::cout << "a.s: " << a.s << std::endl; // print: "a.s: " (as expected,it has been moved)}

作为参数传递“移动”对象成员是否安全?在这种情况下,emplace似乎有效:地图具有预期的关键.

解决方法@H_404_9@ 有趣.出于错综复杂的原因,我认为这是安全的. (为了记录,我也认为这是非常糟糕的风格 – 明确的副本在这里没有任何成本,因为它将被移动到地图中.)

首先,实际的函数调用不是问题. std :: move只将a转换为rvalue引用,而rvalue引用只是引用; a不会马上移动. emplace_back将其参数转发给std :: pair< std :: string,A>的构造函数,这就是事情变得有趣的地方.

那么,使用了std :: pair的构造函数?它有很多,但有两个是相关的:

pair(const T1& x,const T2& y);template<class U,class V> pair(U&& x,U&&y);

(参见标准中的20.3.2),其中T1和T2是std :: pair的模板参数.按照13.3,我们最后用U == const T1&和V == T2,这是直观的意义(否则进入std ::对实际上是不可能的).这给我们留下了表单的构造函数

pair(const T1& x,T2 &&y) : first(std::forward(x)),second(std::forward(y)) { }

按照20.3.2(6-8).

那么,这样安全吗?有用的是,std :: pair的定义有些细节,包括内存布局.特别是,它说明了这一点

T1 first;T2 second;

按顺序排列,所以首先在第二个之前初始化.这意味着在您的特定情况下,字符串将在移走之前被复制,并且您是安全的.

但是,如果你这样做,反过来说:

m.emplace(std::move(A.s),A); // huh?

…然后你会得到有趣的效果.

总结

以上是内存溢出为你收集整理的c – 作为参数传递正在移动的对象的成员是否安全全部内容,希望文章能够帮你解决c – 作为参数传递正在移动的对象的成员是否安全所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/langs/1241829.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-06
下一篇2022-06-06

发表评论

登录后才能评论

评论列表(0条)

    保存