这是我的意思的一个简短的例子。我发现很难简洁地说出这个问题。
struct A {};
struct B : public A {};
void foo(A*&& ap)
{
ap = nullptr;
}
int main()
{
B b;
A* ap = &b;
foo(std::move(ap));
std::cout << (ap == nullptr ? "null" : "not null") << std::endl;
B* bp = &b;
foo(std::move(bp));
std::cout << (bp == nullptr ? "null" : "not null") << std::endl;
}
我希望这会打印
null
null
但是打印
null
not null
快速查看x86反汇编会显示不需要的复制,仅针对B*
案例:
lea eax,[bp]
push eax
call std::move<B * &> (03E14BFh)
add esp,4
mov ecx,dword ptr [eax] << Unwanted copy
mov dword ptr [ebp-0ECh],ecx << occurs here
lea edx,[ebp-0ECh]
push edx
call foo (03E14B5h)
add esp,4
如果没有更改foo
的签名,是否有任何解决方案?对于我可以更改层次结构或foo
函数的内容,我非常受外部API的限制。
答案 0 :(得分:5)
foo
对A*
进行了反驳。您没有给它A*
,而是B*
。这需要转换。形成临时 A*
,绑定到右值引用,更改,最后丢弃。原始B*
永远不会受到影响。