我正在将一个大型项目从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有问题?)
我有两个问题,一个主要的实际问题和一个次要的好奇心问题:
主要:将此代码更改为使用对rvalue-references的标准引用的编码器可能认为move semantics在这种情况下最佳。我可以理解,尽管赋值只涉及复制指针值,但这并不是很有效。 如果它们合适,正确如何使用此代码的rvalue-references?
次要:(仅限好奇心。)2007和2010编译器对此代码的作用是什么?它被读作参考参考吗?这两个&
运算符是否合并并成为单个引用?既然它可能是无效的语法,但它编译得很好,它到底在做什么呢?
答案 0 :(得分:0)
作为问题的解决方案,您可以使用std :: forward。
只需将您的代码更改为:
#include <utility>
CopyAndTakeOwnershipFrom(std::forward<VOperandValue>(oOther));
问题出现是因为你想通过2个函数转发移动语义,但在第一个函数中移动的对象得到一个名字。如果没有std :: forward,它的名字不再是右值,而是一个不能用于T&amp;&amp;的左值的左值。 CopyAndTakeOwnershipFrom中的参数。 之前它在C ++ Builder 2010中运行似乎是一个在XE4中修复的错误。