从旧代码无效使用rvalue引用:我应该如何将其更新为现代正确用法?

时间:2013-08-12 11:12:02

标签: c++ c++builder c++builder-2010

我正在将一个大型项目从C ++ Builder 2010移植到XE4,并且刚刚遇到了这个代码。它在CB2010中编译,运行并显然起作用,并且根据修订日志在我们仍在使用C ++ Builder 2007时添加了。Neither of these compilers supported rvalue references.

VOperandValue& VOperandValue::operator=(VOperandValue&& oOther) {
    // Assignment operator takes full control of all pointers etc, and sets oOther
    // to not own anything
    if (static_cast<void*>(this) != static_cast<void*>(&oOther)) {
        CopyAndTakeOwnershipFrom(oOther);
    }
    return *this;
}

void VOperandValue::CopyAndTakeOwnershipFrom(VOperandValue&& oOther) {
    // Lots of assignments to self's members, and clearing fields of oOther
}

有两点需要注意:

  • operator=故意更改复制的对象。此类包装一次只能由一个对象拥有的资源。这超出了这个问题的范围,但这种行为虽然很奇怪,但却是按照设计的。还有一个复制构造函数和一些其他类似的方法。这些方法适用于复制的对象即将变为无效(例如被破坏)或将被重新用于保存新内容的情况。我不知道为什么static_cast<void*>是比较指向相同类型对象的指针所必需的;对我而言,这似乎是一件非常奇怪的事情。
  • 代码已从使用标准引用(即VOperandValue& oOther)更改为rvalue-references。尽管只支持在C ++ Builder XE(C ++ Builder 2010之后的版本)中添加rvalue引用,但编译器很乐意接受并编译它,并且代码似乎在运行时起作用。

现在这段代码被加载到XE4中,它无法在CopyAndTakeOwnershipFrom(oOther)行编译,但有以下错误:

  

[bcc32错误] OperandValue.cpp(178):E2559无法初始化rvalue   带有'VOperandValue'类型左值的'VOperandValue'类型的引用

     

[bcc32错误] OperandValue.cpp(178):E2342参数类型不匹配   'oOther'(想要'VOperandValue&amp;&amp;',得到'VOperandValue')

(我不明白这些错误,因为第178行是行CopyAndTakeOwnershipFrom(oOther);,并且oOther似乎肯定已在方法参数列表中定义为rvalue-reference。为什么然后呢传递相同的变量时,它与左值非r-ref有问题?)

我有两个问题,一个主要的实际问题和一个次要的好奇心问题:

  1. 主要:将此代码更改为使用对rvalue-references的标准引用的编码器可能认为move semantics在这种情况下最佳。我可以理解,尽管赋值只涉及复制指针值,但这并不是很有效。 如果它们合适,正确如何使用此代码的rvalue-references?

  2. 次要:(仅限好奇心。)2007和2010编译器对此代码的作用是什么?它被读作参考参考吗?这两个&运算符是否合并并成为单个引用?既然它可能是无效的语法,但它编译得很好,它到底在做什么呢?

1 个答案:

答案 0 :(得分:0)

作为问题的解决方案,您可以使用std :: forward。

只需将您的代码更改为:

#include <utility>   
CopyAndTakeOwnershipFrom(std::forward<VOperandValue>(oOther));

问题出现是因为你想通过2个函数转发移动语义,但在第一个函数中移动的对象得到一个名字。如果没有std :: forward,它的名字不再是右值,而是一个不能用于T&amp;&amp;的左值的左值。 CopyAndTakeOwnershipFrom中的参数。 之前它在C ++ Builder 2010中运行似乎是一个在XE4中修复的错误。