c++ - How to properly define a move constructor? -
i did search internet , found 3 ways of defining move constructor:
relying on compiler:
t(t&& other) = default;
dereference
this
pointer:t(t&& other) { *this = std::move(other); }
explicitly reassign members:
t(t&& other) { t.a = other.a; t.b = other.b; //... }
which 1 proper way ? (and second 1 correct?)
the proper generic way move-construct each member, that's defauted version anyway:
t(t && rhs) : a(std::move(rhs.a)) , b(std::move(rhs.b)) { }
as rough rule, should use default definition if need, , should write explicit move constructor if you're doing explicitly implements move semantics, such unique-ownership resource manager:
urm(urm && rhs) : resource(rhs.resource) { rhs.resource = nullptr; }
the indicator whether appropriate whether class has user-defined destructor. in example, destructor release managed resource, , must happen once, moved-from object must modified.
this unrelated, since mentioning assignment operator, here's popular swap-and-assign/swap idiom:
void swap(urm & rhs) noexcept // assume members noexcept-swappable! { using std::swap; swap(resource, rhs.resource); // ... } urm & operator=(urm rhs) noexcept // pass value { rhs.swap(*this); return *this; }
the beauty of approach need 1 single version of assignment operator works temporaries , non-temporaries alike, using move construction when appropriate, , long members well-designed, need 1 single swap
function. on top of that, if swap function doesn't throw (which well-designed class should allow), assignment operator doesn't throw, since possible exceptions occur @ call site.
Comments
Post a Comment