【问题标题】:When is explicit move needed for a return statement?return 语句何时需要显式移动?
【发布时间】:2013-07-03 02:13:20
【问题描述】:

comment to another questionJonathan Wakely 回复我的声明:

对于局部变量函数返回,您永远不需要显式移动 价值。这是隐含的移动

->

...永远不要说永远...如果局部变量,您需要显式移动 与返回类型不同,例如std::unique_ptr<base> f() { auto p = std::make_unique<derived>(); p->foo(); return p; },但是 如果类型相同,它会尽可能移动......

所以有时我们可能不得不在返回时移动一个局部变量。

例子

std::unique_ptr<base> f() { 
  auto p = std::make_unique<derived>();
  p->foo(); 
  return p; 
}

很好,因为它提供了compilation error

> prog.cpp:10:14: error: cannot convert ‘p’ from type
> ‘std::unique_ptr<derived>’ to type ‘std::unique_ptr<derived>&&’

但我想知道一般情况下是否有很好的机会检测到这一点 - 这是语言规则或unique_ptr的限制吗??

【问题讨论】:

    标签: c++ c++11 return implicit-conversion move-semantics


    【解决方案1】:

    更新:

    现代编译器版本不需要显式移动。

    Core DR 1579 更改了规则,因此即使类型不同,返回值也将被视为右值。 GCC 5 为 C++11 和 C++14 实现了新规则。

    原答案:

    这不是unique_ptr 的限制,而是语言的限制,同样的限制适用于任何调用带有右值引用的转换构造函数的return 语句:

    struct U { };
    
    struct T {
      T(U&&) { }
    };
    
    T f() {
      U u;
      return u;  // error, cannot bind lvalue to U&&
    }
    

    这不会编译,因为 [class.copy]/32 说:

    当满足或将满足省略复制操作的条件时,除了源对象是函数参数的事实,并且要复制的对象由左值指定时,重载决策选择构造函数首先执行复制,就好像对象是由右值指定的一样。

    这意味着 return 语句中的表达式只有在符合复制/移动省略(又名 NRVO)的条件时才能被视为右值,但这太严格了,因为这意味着它仅适用于类型完全正确的情况同样,即使变量总是超出范围,所以总是将 is 视为右值是合理的(从技术上讲,它是一个 xvalue,一个 expiring 值。)

    这是最近 suggestedRichard Smith(之前由 Xeo 提供)提供的,我认为这是一个非常好的主意。

    【讨论】:

    • 很久以前,我最初将此建议发送给 Mike 和 Richard,以供在 Bristol 考虑,但他们似乎没有得到它。 :(
    • 哦,here 是相关的核心/进化问题。再次浏览我的邮件,似乎 Jeffrey Yasskin 真的打败了我。不过,我添加了从局部变量的子对象中移动的建议。 :)
    • @Xeo 单个对象的合理状态不一定是它包含的更大对象的上下文中的合理状态。对于公共成员当然不应该(因为任何人都可以设置它们),但是可以 100% 确定,许多人滥用公共成员并且(希望记录在案)对他们可能或可能不包含。因此,这样的更改可能会破坏遗留代码。
    • 该成员可能不是公开的,您可能从可以访问该对象的朋友或成员函数返回它。我同意@Joe 的观点,即移动对象的 part 可能会破坏其不变量,因此您要么需要一种方法来显式禁用隐式移动,要么保守而不是为子对象执行此操作
    • 这应该更新以反映open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1579的分辨率
    猜你喜欢
    • 2017-04-14
    • 2016-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多