1

这是我的意思的一个快速的最小示例。我发现很难简洁地表达这个问题。

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吗?我非常受外部 API 的限制,无法更改层次结构或foo函数。

4

1 回答 1

6

foo引用 a A*。你不给它一个A*,而是一个B*。这需要转换。一个临时 A*的被形成,绑定到右值引用,改变,最后被丢弃。原件B*永远不会受到影响。

于 2013-09-16T21:48:51.640 回答