.. ot-topic:: cxx11.new_language_features.move_pf.livehack_string_move :dependencies: cxx11.new_language_features.move_pf.overview .. include:: Implementing Move Semantics (``class String``, Live Hacked) =========================================================== .. contents:: :local: Copy Semantics, Revisited ------------------------- .. sidebar:: **See also** * :doc:`/trainings/material/soup/cxx03/020-data-encapsulation/object-copy` * Copy semantics is complicated when resources are maintained (e.g. dynamic memory is allocated) * Compiler generated copy semantics is exactly *counter-bugfree* in such situations * |longrightarrow| *pointers* are copied, not the resources that they point to ``class String``, Without Copy ------------------------------ * ``class String`` again * *Copy* explicitly deleted (added again later) * |longrightarrow| neither *copy* nor *move* (remember: move is generated by compiler only when no dtor or copy is there * Implementation .. literalinclude:: code/string-10.h :caption: :download:`code/string-10.h` :language: c++ * Basic functionality/usage (other than copy/move) .. literalinclude:: code/string-10-suite.cpp :caption: :download:`code/string-10-suite.cpp` :language: c++ Return From Function: *Copy (Or Move) Wanted* --------------------------------------------- * Copy explicitly deleted * Rules: no *move* semantics either (we don't know what that is anyway) * *Return from function?* .. literalinclude:: code/string-10-suite-bogus.cpp :caption: :download:`code/string-10-suite-bogus.cpp` :language: c++ * No move, no copy * |longrightarrow| error .. code-block:: console code/string-10-suite-bogus.cpp:8:12: error: use of deleted function ‘String::String(const String&)’ Move Constructor? Move? ----------------------- .. code-block:: c++ String make_a_string_from(const char* s) { String ret_s(s); return ret_s; // <--- proven: ret_s not accessible past this point } * Local variable ``ret_s`` not accessible anymore after ``return``, obviously * No need for a *copy* altogether which would be * Allocate destination (caller's function value) * Copy source (``ret_s`` to destination) * Free source (``ret_s``) * |longrightarrow| enter *move*: transfer source to destination without copying * Compiler knows all that * |longrightarrow| can insert move constructor to transfer returned value to final location Implementing Move Constructor ----------------------------- * Prototype: ``String(String&& from) noexcept`` * Transfers guts of ``from`` into ``this`` * ``noexcept`` is good practice but not required * Invalidates ``from`` |longrightarrow| resources not deleted twice * *Attention*: invalidated object should still be usable! .. literalinclude:: code/string-20.h :caption: :download:`code/string-20.h` :language: c++ .. literalinclude:: code/string-20-suite.cpp :caption: :download:`code/string-20-suite.cpp` :language: c++ .. note:: The manual operations (move ``_c_str`` from there to here, and invalidated there) can also be written as .. code-block:: c++ #include String(String&& from) noexcept : _c_str(std::exchange(from._c_str, nullptr) {} And Move Assignment? -------------------- .. literalinclude:: code/string-20-suite-bogus.cpp :caption: :download:`code/string-20-suite-bogus.cpp` :language: c++ * (Copy) assignment was deleted * No move assignment * |longrightarrow| no assigment .. code-block:: console code/string-20-suite-bogus.cpp:14:35: error: use of deleted function ‘String& String::operator=(const String&)’ Implementing Move Assignment ---------------------------- * Prototype: ``String& operator=(String&&) noexcept`` * Transfers guts, and invalidates source (just like move constructor) * Much like copy assignment |longrightarrow| *self assignment check* .. literalinclude:: code/string-30.h :caption: :download:`code/string-30.h` :language: c++