为什么C ++ 11对值参数有隐式移动,但对于右值参数不是隐式移动? [英] Why does C++11 have implicit moves for value parameters, but not for rvalue parameters?

查看:100
本文介绍了为什么C ++ 11对值参数有隐式移动,但对于右值参数不是隐式移动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C ++ 11中,值参数(和其他值)在返回时享受隐式移动:

  A func a){
return a; //如果存在则使用A :: A(A&& amp;)如果存在
,则使用A :: A

至少在MSVC 2010中,右值引用参数需要 std :: move

  A func(A& a){
return a; //即使存在A :: A(A&&),也使用A :: A(A&&)存在
}

我想象内部函数中,右值引用和值表现相似,唯一的区别是,在值的情况下,函数本身负责销毁,而对于右值引用,责任

解决方案



div>

标准化委员会花费巨大的努力来创建措辞,以便只有在两种情况下才会发生迁移:


  1. 要求(通过 std :: move / code>或类似的转换)。

值参数将无疑在函数结束时被销毁。因此,通过移动返回显然是安全的;它不能被其他代码触摸后返回(除非你故意试图打破的东西,在这种情况下你可能触发未定义的行为)。因此,它可以在返回中移动。



A &&& 临时。但它可以是指一个左值(一个命名变量)。因此,从它移动是不安全的;原始变量可能潜伏在周围。由于你没有明确地要求从中移动(即:你在这个函数中没有调用 std :: move ),没有



&& 变量只会隐式移动没有 std :: move )是当您返回时。 std :: move< T> 返回 T&&



现在,调用 A func非常困难,因为它是一个返回值。 (或等效强制类型)调用 std :: move 的左值(A& 。因此,技术上来说,&&& 类型的参数应该隐式移动。但标准委员会希望对&& 类型进行明确的移动,只是为了确保移动不会在此函数的范围内隐式发生。也就是说,它不能使用函数外部的关于&& 的来源的知识。



一般来说,在两种情况下,你应该只使用&&& 参数:要么是编写移动构造函数(或者移动赋值运算符,由值完成),或者你正在写一个转发函数。可能还有其他一些情况,但你不应该把&&& 添加到类型中,除非你有一些特别的东西。如果 A 是可移动类型,则只需按值。


In C++11, value parameters (and other values) enjoy implicit move when returned:

A func(A a) {
    return a; // uses A::A(A&&) if it exists
}

At least in MSVC 2010, rvalue reference parameters need std::move:

A func(A && a) {
    return a; // uses A::A(A const&) even if A::A(A&&) exists
}

I would imagine that inside functions, an rvalue reference and a value behave similar, with the only difference that in case of values, the function itself is responsible for destruction, while for rvalue references, the responsibility is outside.

What is the motivation for treating them differently in the standard?

解决方案

The standardization committee expended great effort in creating wording so that moves would only ever happen in exactly two circumstances:

  1. When it is clearly safe to do so.
  2. When the user explicitly asks (via std::move or a similar cast).

A value parameter will unquestionably be destroyed at the end of the function. Therefore, returning it by move is clearly safe; it can't be touched by other code after the return (not unless you're deliberately trying to break things, in which case you probably triggered undefined behavior). Therefore, it can be moved from in the return.

A && variable could be referring to a temporary. But it could be referring to an lvalue (a named variable). It is therefore not clearly safe to move from it; the original variable could be lurking around. And since you didn't explicitly ask to move from it (ie: you didn't call std::move in this function), no movement can take place.

The only time a && variable will be implicitly moved from (ie: without std::move) is when you return it. std::move<T> returns a T&&. It is legal for that return value to invoke the move constructor, because it is a return value.

Now it is very difficult to call A func(A &&a) with an lvalue without calling std::move (or an equivalent cast). So technically, it should be fine for parameters of && type to be implicitly moved from. But the standards committee wanted moves to be explicit for && types, just to make sure that movement didn't implicitly happen within the scope of this function. That is, it can't use outside-of-function knowledge about where the && comes from.

In general, you should only take parameters by && in two cases: either you're writing a move constructor (or move assignment operator, but even that can be done by value), or you're writing a forwarding function. There may be a few other cases, but you shouldn't take && to a type unless you have something special in mind. If A is a moveable type, then just take it by value.

这篇关于为什么C ++ 11对值参数有隐式移动,但对于右值参数不是隐式移动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆