Function taking rvalue reference of a base class pointer is having pointers from derived classes copied

StackOverflow https://stackoverflow.com/questions/18837835

  •  28-06-2022
  •  | 
  •  

Question

Here's a quick minimal example of what I mean. I found it hard to succinctly phrase the question.

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;
}

I hoped this would print

null
null

but instead it prints

null
not null

A quick look at the x86 disassembly shows the unwanted copying occurring, only for the B* case:

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  

Is there any solution to this without changing the signature of foo? I'm very constrained by an external API as to what I can change about the hierarchy or the foo function.

Was it helpful?

Solution

foo takes a refence to an A*. You don't give it an A*, but instead a B*. This necessitates a conversion. A temporary A* is formed, bound to the rvalue reference, changed, and finally discarded. The original B* is never affected.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top