diff --git a/notebooks/14_MoveSemantics+RuleOfSix.ipynb b/notebooks/14_MoveSemantics+RuleOfSix.ipynb
index 67cfdf0a2fb6542e6571e5733e1487542fb6574f..6edac924c24b8348c89367431af00c30b66a8b89 100644
--- a/notebooks/14_MoveSemantics+RuleOfSix.ipynb
+++ b/notebooks/14_MoveSemantics+RuleOfSix.ipynb
@@ -1 +1 @@
-{"metadata":{"language_info":{"codemirror_mode":"text/x-c++src","file_extension":".cpp","mimetype":"text/x-c++src","name":"c++","version":"17"},"kernelspec":{"name":"xcpp17","display_name":"C++17","language":"C++17"}},"nbformat_minor":5,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Move Semantics","metadata":{},"id":"4c244310-2195-4b50-a923-df0b9ba15f7d"},{"cell_type":"code","source":"#include <algorithm>\n#include <iostream>\n#include <vector>\n\nclass BigArrayCopy {\n\npublic:\n\n  BigArrayCopy( size_t len ) : len_( len ), data_( new int[ len ] ) {}\n\n  BigArrayCopy( const BigArrayCopy& other ) : len_( other.len_ ),\n                                              data_( new int[ other.len_ ] ) {\n    std::cout << \"copy construction of \" << other.len_ << \" elements\" << std::endl;\n    std::copy( other.data_, other.data_ + len_, data_ );\n  }\n\n  BigArrayCopy& operator=( const BigArrayCopy& other ) {\n\n    std::cout << \"copy assignment of \" << other.len_ << \" elements\" << std::endl;\n\n    if( this != &other ) {\n\n      delete[] data_;\n      len_ = other.len_;\n      data_ = new int[ len_ ];\n\n      std::copy( other.data_, other.data_ + len_, data_ );\n\n    }\n\n    return *this;\n  }\n\n  ~BigArrayCopy() {\n    if( data_ != nullptr ) {\n      delete[] data_;\n    }\n  }\nprivate:\n\n  size_t len_;\n  int* data_;\n\n};","metadata":{"trusted":true},"execution_count":2,"outputs":[],"id":"4ffa9b8d-02be-4919-882c-18556a6ded7d"},{"cell_type":"code","source":"int main() {\n    \n  std::vector< BigArrayCopy > myVec;\n\n  BigArrayCopy bArray( 11111111 );\n  BigArrayCopy bArray2( bArray );\n\n  myVec.push_back( bArray );\n  bArray = BigArrayCopy( 22222222 );\n  myVec.push_back( BigArrayCopy( 33333333 ) );\n\n}\n\nmain();","metadata":{"trusted":true},"execution_count":4,"outputs":[{"name":"stdout","text":"copy construction of 11111111 elements\ncopy construction of 11111111 elements\ncopy assignment of 22222222 elements\ncopy construction of 33333333 elements\ncopy construction of 11111111 elements\n","output_type":"stream"}],"id":"dd1e7485-7b8e-4728-a217-df899e07d6d8"},{"cell_type":"markdown","source":"# Rule of Six / Five / Zero","metadata":{},"id":"aa620485-bd12-4727-9c7f-d07f66d0e62a"},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[],"id":"a07bc870-4ffc-462a-bce0-ae82a40b625b"}]}
\ No newline at end of file
+{"metadata":{"language_info":{"codemirror_mode":"text/x-c++src","file_extension":".cpp","mimetype":"text/x-c++src","name":"c++","version":"17"},"kernelspec":{"name":"xcpp17","display_name":"C++17","language":"C++17"}},"nbformat_minor":5,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Move Semantics","metadata":{},"id":"4c244310-2195-4b50-a923-df0b9ba15f7d"},{"cell_type":"markdown","source":"In order to understand what this is about let us take a look at an example from Rainer Grimm's blog \"Modernes C++ in der Praxis\":","metadata":{},"id":"92b6cf27-b829-4efd-9395-e38f3a330bb4"},{"cell_type":"code","source":"#include <algorithm>\n#include <iostream>\n#include <vector>\n\nclass BigArrayCopy {\n\npublic:\n\n  BigArrayCopy( size_t len ) : len_( len ), data_( new int[ len ] ) {}\n\n  BigArrayCopy( const BigArrayCopy& other ) : len_( other.len_ ),\n                                              data_( new int[ other.len_ ] ) {\n    std::cout << \"copy construction of \" << other.len_ << \" elements\" << std::endl;\n    std::copy( other.data_, other.data_ + len_, data_ );\n  }\n\n  BigArrayCopy& operator=( const BigArrayCopy& other ) {\n\n    std::cout << \"copy assignment of \" << other.len_ << \" elements\" << std::endl;\n\n    if( this != &other ) {\n\n      delete[] data_;\n      len_ = other.len_;\n      data_ = new int[ len_ ];\n\n      std::copy( other.data_, other.data_ + len_, data_ );\n\n    }\n\n    return *this;\n  }\n\n  ~BigArrayCopy() {\n    if( data_ != nullptr ) {\n      delete[] data_;\n    }\n  }\nprivate:\n\n  size_t len_;\n  int* data_;\n\n};","metadata":{"trusted":true},"execution_count":2,"outputs":[],"id":"4ffa9b8d-02be-4919-882c-18556a6ded7d"},{"cell_type":"code","source":"int main() {\n    \n  std::vector< BigArrayCopy > myVec;\n\n  BigArrayCopy bArray( 11111111 );\n  BigArrayCopy bArray2( bArray );\n\n  myVec.push_back( bArray );\n  bArray = BigArrayCopy( 22222222 );\n  myVec.push_back( BigArrayCopy( 33333333 ) );\n\n}\n\nmain();","metadata":{"trusted":true},"execution_count":3,"outputs":[{"name":"stdout","text":"copy construction of 11111111 elements\ncopy construction of 11111111 elements\ncopy assignment of 22222222 elements\ncopy construction of 33333333 elements\ncopy construction of 11111111 elements\n","output_type":"stream"}],"id":"dd1e7485-7b8e-4728-a217-df899e07d6d8"},{"cell_type":"markdown","source":"Let us analyse the output. Where do the five copies come frome?\n\n\n\n\n\n\n\n \n \n \n","metadata":{},"id":"333e1d6f-aab5-4c70-859d-db4dafb02981"},{"cell_type":"markdown","source":"We can change that by adding a **move constructor** and a **move assignment operator** to our class:","metadata":{},"id":"6893f7df-99e0-44e9-a79f-8c6e8acba110"},{"cell_type":"code","source":"#include <algorithm>\n#include <iostream>\n#include <vector>\n\nusing std::cout;\nusing std::endl;\nusing std::vector;\n\nclass BigArray {\n\npublic:\n\n  BigArray( size_t len ) : len_( len ), data_( new int[ len ] ) {}\n\n  BigArray( const BigArray& other ) : len_( other.len_ ),\n                                              data_( new int[ other.len_ ] ) {\n    cout << \"copy construction of \" << other.len_ << \" elements\" << endl;\n    std::copy( other.data_, other.data_ + len_, data_ );\n  }\n\n  BigArray& operator=( const BigArray& other ) {\n\n    cout << \"copy assignment of \" << other.len_ << \" elements\" << endl;\n\n    if( this != &other ) {\n\n      delete[] data_;\n      len_ = other.len_;\n      data_ = new int[ len_ ];\n\n      std::copy( other.data_, other.data_ + len_, data_ );\n\n    }\n\n    return *this;\n  }\n\n  BigArray( BigArray&& other ) : len_( other.len_ ),\n                                              data_( other.data_ ) {\n    cout << \"move construction of \" << other.len_ << \" elements\" << endl;\n    other.len_ = 0;\n    other.data_ = nullptr;\n  }\n\n  BigArray& operator=( BigArray&& other ) {\n\n    cout << \"move assignment of \" << other.len_ << \" elements\" << endl;\n\n    if( this != &other ) {\n\n      delete[] data_;\n\n      len_ = other.len_;\n      data_ = other.data_;\n\n      other.len_ = 0;\n      other.data_ = nullptr;\n    }\n\n    return *this;\n  }\n\n  ~BigArray() {\n    if( data_ != nullptr ) {\n      delete[] data_;\n    }\n  }\nprivate:\n\n  size_t len_;\n  int* data_;\n\n};","metadata":{"trusted":true},"execution_count":1,"outputs":[],"id":"e3784252-4e44-4260-a5a1-d2b92f92e264"},{"cell_type":"code","source":"int main() {\n    \n  std::vector< BigArray > myVec;\n  myVec.reserve(2); // get's rid of the final copy operation, when myVec was reallocated\n\n  BigArray bArray( 11111111 );\n  BigArray bArray2( bArray );\n\n  myVec.push_back( bArray );\n  bArray = BigArray( 22222222 );\n  myVec.push_back( BigArray( 33333333 ) );\n\n}\n\nmain();","metadata":{"trusted":true},"execution_count":4,"outputs":[{"name":"stdout","text":"copy construction of 11111111 elements\ncopy construction of 11111111 elements\nmove assignment of 22222222 elements\nmove construction of 33333333 elements\n","output_type":"stream"}],"id":"ebbe2374-3d00-4340-98a0-9352ff8ca2cb"},{"cell_type":"markdown","source":"As we can see the assignment and copying of the two temporaries in lines # 10 and 11 now uses our **move semantics**.\n\nBut what is does the **\"&&\"** in the interface of the two methods represent? It is an **r-value reference**.\n","metadata":{},"id":"2fead1ad-cee3-4a0d-ba70-b14066a349b9"},{"cell_type":"markdown","source":"### R-Value References\n\nFirst of all, what are \"r-values\"? Complicated question, short simplified answer, stuff that can appear on the right-hand side of an assignment, hence the name (originally). Examples of r-values are:\n\n- temporary objects\n- unnamed objects\n- objects whose address is undeterminable\n\nsuch as\n\n```\nint fourtyTwo = 42;\nstd::string a = std::string( \"rhs is an rvalue\");\nstd::string b = std::string( \"r\" ) +  std::string( \"-value\" );\nstd::string c = a + b;\nstd::string d = std::move(b);\n```\n\nThe last line is especially interesting. [std::move](https://en.cppreference.com/w/cpp/utility/move) effectively returns an r-value reference for its argument:\n\n\n> std::move is used to indicate that an object t may be \"moved from\", i.e. allowing the efficient transfer of resources from t to another object. In particular, std::move produces an xvalue expression that identifies its argument t. It is exactly equivalent to a static_cast to an rvalue reference type. ","metadata":{},"id":"a2f2682a-1823-46c4-a444-a23fc192ef17"},{"cell_type":"code","source":"int value = 1;\nint& lRef1 = value;\n// int&& rRef1 = value;\nint&& rRef2 = 1;\nconst int& lRef2 = 1;","metadata":{"trusted":true},"execution_count":7,"outputs":[],"id":"7c569151-43ef-44a8-babc-6928ca17b626"},{"cell_type":"markdown","source":"An r-value can bind to an r-value reference, but also to a constant l-value reference. That's why `BigArrayCopy` worked after all. However, binding to an r-value reference, if possible has **higher precedence**. That's what we need in `BigArray` for the move methods.","metadata":{},"id":"1ad6ad50-160f-49d9-b486-2ac84c1cbdbb"},{"cell_type":"markdown","source":"# Rule of Six / Five / Zero","metadata":{},"id":"aa620485-bd12-4727-9c7f-d07f66d0e62a"},{"cell_type":"markdown","source":"The advantage of *move semantics* is that it helps to avoid unnecessary copy operations in order to increase performance. However, it also means that a simple class now could implement the following six different construction/destruction/assigment methods:","metadata":{},"id":"6549163b-b1f8-4d7b-9126-0674f01d0022"},{"cell_type":"code","source":"class simple {\n    \n    // Default Constructor\n    simple() {};\n    \n    // Destructor\n    ~simple(){};\n    \n    // Copy Constructor\n    simple( const simple& other ) {};\n    \n    // Copy Assigment\n    simple& operator= ( const simple& other ) {\n        simple* aux = new( simple );\n        // copy stuff from other to aux\n        return *aux;\n    };\n    \n    // Move Constructor\n    simple( const simple&& other ) {};\n    \n    // Move Assignment\n    simple& operator= ( const simple&& other ) {\n        simple* aux = new( simple );\n        // move stuff from other to aux\n        // and potentially set other to 'zero'\n        return *aux;\n    };\n}","metadata":{"trusted":true},"execution_count":14,"outputs":[],"id":"381417d5-fe96-4249-a509-29fcfdd5615b"},{"cell_type":"markdown","source":"The question is, what happens, if we implement none or only some of these methods? For example we know that a default constructor will always be generated automatically by the compiler, if we do not interdict this by deleting it.","metadata":{},"id":"4ef8a01b-806b-43b5-9401-5b266143b9e8"},{"cell_type":"code","source":"https://www.heise.de/blog/Programmiersprache-C-Rule-of-Zero-or-Six-7463520.html","metadata":{"trusted":true},"execution_count":15,"outputs":[],"id":"ebe84f93-58ad-47c0-8ae6-9817fab5b867"},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[],"id":"e45f50e1-2fe8-4a3b-ba00-05edcc21a62b"}]}
\ No newline at end of file