Is the following move constructor code safe?

后端 未结 3 1420
走了就别回头了
走了就别回头了 2020-12-31 02:56

This is the move constructor of class X:

X::X(X&& rhs)
    : base1(std::move(rhs))
    , base2(std::move(rhs))
    , mbr1(std::move(rhs.         


        
3条回答
  •  春和景丽
    2020-12-31 03:09

    This is approximately how an implicit move constructor typically works: each base and member subobject is move-constructed from the corresponding subobject of rhs.

    Assuming that base1 and base2 are bases of X that do not have constructors taking X / X& / X&& / const X&, it's safe as written. std::move(rhs) will implicitly convert to base1&& (respectively base2&&) when passed to the base class initializers.

    EDIT: The assumption has actually bitten me a couple of times when I had a template constructor in a base class that exactly matched X&&. It would be safer (albeit incredibly pedantic) to perform the conversions explicitly:

    X::X(X&& rhs)
        : base1(std::move(static_cast(rhs)))
        , base2(std::move(static_cast(rhs)))
        , mbr1(std::move(rhs.mbr1))
        , mbr2(std::move(rhs.mbr2))
    {}
    

    or even just:

    X::X(X&& rhs)
        : base1(static_cast(rhs))
        , base2(static_cast(rhs))
        , mbr1(std::move(rhs.mbr1))
        , mbr2(std::move(rhs.mbr2))
    {}
    

    which I believe should exactly replicate what the compiler would generate implicitly for X(X&&) = default; if there are no other base classes or members than base1/base2/mbr1/mbr2.

    EDIT AGAIN: C++11 §12.8/15 describes the exact structure of the implicit member-wise copy/move constructors.

提交回复
热议问题