C++中什么时候使用std::move​

发布时间:2021-11-26 13:53:09 作者:iii
来源:亿速云 阅读:429

这篇文章主要讲解了“C++中什么时候使用std::move”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++中什么时候使用std::move”吧!

ES.56:只在需要将一个对象显式移动到另外的作用域时使用std::move

Reason(原因)

我们使用move而不是copy是为了避免不必要的重复并提高性能。

移动操作一般会留下一个空对象(C.64),它可能引起误解甚至危险。因此我们努力避免移动左值(它们可能在后续代码中被使用)。

Notes(注意)

如果源数据是右值,移动操作会隐式进行(例如return处理或函数的返回值),在这种情况下进行显式移动操作,会导致代码被漫无目标地的复杂化。相反,编写带返回值的简短函数,这样无论是函数的返回值还是调用侧的接受动作都可以很自然地被优化。

通常情况下,遵循本文档中的准则(包括不要不必要地扩大变量作用域,编写带返回值的简短函数,返回局部变量等)可以帮助消除显式执行std::move的大部分需求。

在显式移动一个对象到另外的作用域时,显式移动是有必要的。特别是:

1.将对象传递给一个“下沉”函数时(接管变量所有权的函数,译者注)

2.实现对象自身移动操作(移动构造函数,移动赋值运算符)和交换操作时

Example, bad(反面示例)

void sink(X&& x);   // sink takes ownership of x

void user()
{
   X x;
   // error: cannot bind an lvalue to a rvalue reference
   sink(x);
   // OK: sink takes the contents of x, x must now be assumed to be empty
   sink(std::move(x));

   // ...

   // probably a mistake
   use(x);
}

通常情况下,std::move()作为为&&参数提供实参。而且在移动之后,应该认为对象已经被移走(参见C.64)并且在赋予新值之前不要获取对象的状态。

void f() {
   string s1 = "supercalifragilisticexpialidocious";

   string s2 = s1;             // ok, takes a copy
   assert(s1 == "supercalifragilisticexpialidocious");  // ok

   // bad, if you want to keep using s1's value
   string s3 = move(s1);

   // bad, assert will likely fail, s1 likely changed
   assert(s1 == "supercalifragilisticexpialidocious");
}
Example(示例)
void sink(unique_ptr<widget> p);  // pass ownership of p to sink()

void f() {
   auto w = make_unique<widget>();
   // ...
   sink(std::move(w));               // ok, give to sink()
   // ...
   sink(w);    // Error: unique_ptr is carefully designed so that you cannot copy it
}
Notes(注意)

std::move()实际上是目标为&&的类型转换;它自己不会移动任何东西,而是将命名对象标记为一个移出操作的候选者。语言已经知道对象可以被移出的一般情况,特别是函数的返回值,因此不要因为多余的std::move导致代码复杂化。

永远不要只是因为听说它更高效就使用std::move。通常不要相信那些脱离具体数据的所谓“高效”。通常不要没有理由地让代码复杂化。永远不要对常量对象调用std::move(),这会不知不觉地产生一个拷贝。

Example, bad(反面示例)

vector<int> make_vector() {
   vector<int> result;
   // ... load result with data
   return std::move(result);       // bad; just write "return result;"
}

永远不要返回局部变量的移动结果;因为语言已经知道这个变量可以作为移动操作的候选,在这种代码中增加move代码不但没有任何帮助,而且对于某些编译器,由于产生了额外的指向局部变量的引用,增加move代码会影响RVO(返回值优化)的正常执行。

Example, bad(反面示例)

vector<int> v = std::move(make_vector());   // bad; the std::move is entirely redundant

如果函数f以传值方式返回结果,永远不要对这个返回值调用move操作,例如X=move(f());语言已经知道返回值是临时变量并且可以进行移出操作。

Example(示例)

void mover(X&& x) {
   call_something(std::move(x));         // ok
   call_something(std::forward<X>(x));   // bad, don't std::forward an rvalue reference
   call_something(x);                    // suspicious, why not std::move?
}

template<class T>
void forwarder(T&& t) {
   call_something(std::move(t));         // bad, don't std::move a forwarding reference
   call_something(std::forward<T>(t));   // ok
   call_something(t);                    // suspicious, why not std::forward?
}
Enforcement(实施建议)

感谢各位的阅读,以上就是“C++中什么时候使用std::move”的内容了,经过本文的学习后,相信大家对C++中什么时候使用std::move这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

推荐阅读:
  1. C++统计精确时间
  2. c++中 seekg seekp tellg tellp 的简单用法

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c++

上一篇:如何通过ambari界面安装集群的各个组件

下一篇:C#如何实现基于Socket套接字的网络通信封装

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》