1

我正在将一个大型项目从 C++ Builder 2010 移植到 XE4,并且刚刚遇到此代码。它在 CB2010 中编译、运行并且显然可以工作,并且根据修订日志是在我们仍在使用 C++ Builder 2007 时添加 的。这些编译器都不支持右值引用。

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)更改为右值引用。尽管仅在 C++Builder XE(C++Builder 2010 之后的版本)中添加了对右值引用的支持,但编译器很高兴地接受并编译了它,并且代码在运行时似乎可以正常工作。

现在这段代码被加载到XE4中,编译失败就行CopyAndTakeOwnershipFrom(oOther)了,错误如下:

[bcc32 错误] OperandValue.cpp(178):E2559 无法使用“VOperandValue”类型的左值初始化“VOperandValue”类型的右值引用

[bcc32 错误] OperandValue.cpp(178):E2342 参数“oOther”中的类型不匹配(需要“VOperandValue &&”,得到“VOperandValue”)

(我不明白这些错误,因为第 178 行是第 178 行CopyAndTakeOwnershipFrom(oOther);,并且oOther似乎肯定已在方法参数列表中定义为右值引用。为什么在传递时遇到左值非 r-ref 的问题同一个变量?)

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

  1. 主要:将这段代码从使用标准引用更改为右值引用的编码人员可能认为移动语义在这种情况下是最好的。我可以理解,虽然赋值只涉及复制指针值,这不是很多工作。 如果它们合适,我将如何正确使用此代码的右值引用?

  2. 次要:(仅限好奇心。)2007 年和 2010 年的编译器对这段代码做了什么?它是否被视为对参考的参考?这两个&运算符是否合并并成为一个单一的参考?既然它可能是无效的语法,但它编译并运行良好,它到底在做什么?

4

1 回答 1

0

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

只需将您的代码更改为:

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

出现问题是因为您想通过 2 个函数向前移动语义,但在第一个函数中,移动的对象得到了一个名称。有了名称,它不再是没有 std::forward 的右值,而是一个不能用于 CopyAndTakeOwnershipFrom 中的 T&& 参数的左值。它以前在 C++ Builder 2010 中工作似乎是一个在 XE4 中得到修复的错误。

于 2014-04-18T16:58:48.447 回答