If a member of type unique_ptr or shared_ptr is move-constructed from
a parameter in ctor-init, the parameter will be left with nullptr at
the completion of member's initialization. If the parameter's and
member's names are the same, use of member's name in the constructor
body will not refer to the member, but to the parameter.
#include <memory> struct X { int v; X() : v() { } int f() { return v + 42; } }; struct Y { std::unique_ptr<X> p; int x; explicit Y(std::unique_ptr<X> p) : p{std::move(p)} { x = p->f(); // 'p' is nullptr decltype(p->f()) v = x; // ignore unevaluated context } int f() const { return x; } }; int main() { std::unique_ptr<X> p(new X); Y y(std::move(p)); return y.f(); }
I'm not sure how much of an efficiency concern there is doing a generic RAV here, rather than something more targeted. I mean I suppose in general the std::move could happen in any subexpression of an init - but I assume the case you're trying to catch here is just the one where the name of the parameter and variable are the same (or very similar - like foo_ and foo, etc) and the user accidentally uses the parameter instead of the variable they moved-in-to?