diff --git a/5-UsefulConceptsAndSTL/3-Containers.ipynb b/5-UsefulConceptsAndSTL/3-Containers.ipynb
index 5df13e9859e8d05426da399e238c375377b68575..c9e54b8090ea7e86708e1e66a5439edebe49d804 100644
--- a/5-UsefulConceptsAndSTL/3-Containers.ipynb
+++ b/5-UsefulConceptsAndSTL/3-Containers.ipynb
@@ -589,9 +589,7 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "It may not extremely efficient: at each call to `operator[]`, the program must figure out the element to draw without using the fact it had just fetched the element just in the previous memory location (in practice now compilers are rather smart and figure this out...)\n",
-    "\n",
-    "Iterators provides this (possibly) more efficient access:"
+    "Iterators provides another way to access same data (which used to be more efficient but now compilers are cleverer and both are equivalent):"
    ]
   },
   {
@@ -736,9 +734,9 @@
     "`std::vector` is not the only possible choice; I will present very briefly the other possibilities here:\n",
     "\n",
     "* `std::list`: A double-linked list: the idea is that each element knows the addresses of the element before and the element after. It might be considered if you need to add often elements at specific locations in the list: adding a new element is just changing 2 pointers and setting 2 new ones. You can't access directly an element by its index with a `std::list`.\n",
-    "* `std::slist`: A single-linked list: similar as a `std::list` except only the pointer to the next element is kept.\n",
+    "* `std::forward_list`: A single-linked list: similar as a `std::list` except only the pointer to the next element is kept. This is a C++ 11 addition.\n",
     "* `std::deque`: For \"double ended queue\"; this container may be helpful if you need to store a really huge amount of data that might not fit within a `std::vector`. It might also be of use if you are to add often elements in front on the list: there is `push_front()` method as well as a `push_back` one. Item 18 of [Effective STL](http://localhost:8888/lab/tree/bibliography.ipynb#Effective-STL) recommends using `std::deque` with `bool`: `std::vector<bool>` was an experiment to provide a specific implementation to spare memory when storing booleans that went wrong and should therefore be avoided...\n",
-    "* `std::array`: You should use this one if the number of elements is known at compile time and doesn't change at all, as compiler may provide even more optimizations than for `std::vector` (and your end user can't by mistake modify its size).\n",
+    "* `std::array`: You should use this one if the number of elements is known at compile time and doesn't change at all, as compiler may provide even more optimizations than for `std::vector` (and your end user can't by mistake modify its size). This is a C++ 11 addition.\n",
     "* `std::string`: Yes, it is actually a container! I will not tell much more about it; just add that it is the sole container besides `std::vector` and `std::array` that ensures contiguous storage."
    ]
   },
diff --git a/5-UsefulConceptsAndSTL/4-AssociativeContainers.ipynb b/5-UsefulConceptsAndSTL/4-AssociativeContainers.ipynb
index 6952a4d1c6cf9ffcab984fb79037a200a6025c92..c126cbc6b2e305ae451f59a00f95f9c565616ba3 100644
--- a/5-UsefulConceptsAndSTL/4-AssociativeContainers.ipynb
+++ b/5-UsefulConceptsAndSTL/4-AssociativeContainers.ipynb
@@ -402,7 +402,7 @@
     "\n",
     "It might be used for instance if you want to keep a list of stuff you have encountered at least once: you don't care about how many times, but you want to know if it was encountered at least once. A `std::vector` would be inappropriate: you would have to look up its whole content before each insertion. With a `std::set` it is already built-in in the class.\n",
     "\n",
-    "## std::unordered_map\n",
+    "## `std::unordered_map`\n",
     "\n",
     "This is another associative container introduced in C++ 11, with a different trade-off (and closer to a `dict` in Python for instance):\n",
     "\n",
diff --git a/5-UsefulConceptsAndSTL/6-SmartPointers.ipynb b/5-UsefulConceptsAndSTL/6-SmartPointers.ipynb
index edf490553a7fee92c2964cdb72e326190f89c3b2..4c36d9e90cd8cf7b3de4544932ae2c9414341cf7 100644
--- a/5-UsefulConceptsAndSTL/6-SmartPointers.ipynb
+++ b/5-UsefulConceptsAndSTL/6-SmartPointers.ipynb
@@ -132,7 +132,7 @@
     "int main([[maybe_unused]] int argc, [[maybe_unused]] char** argv)\n",
     "{\n",
     "    auto ptr = std::make_unique<int>(5);\n",
-    "    auto copy = std::move(ptr);\n",
+    "    auto moved_ptr = std::move(ptr);\n",
     "    \n",
     "    std::cout << \"Beware as now there are no guarantee upon the content of ptr: \" << *ptr << std::endl; // EXPECTED RUNTIME ISSUE!\n",
     "\n",
@@ -306,9 +306,28 @@
    "source": [
     "### Releasing a `unique_ptr`\n",
     "\n",
-    "To free manually the content of a `unique_ptr`:\n",
+    "To free manually the content of a `unique_ptr`, assign `nullptr` to the pointer:"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "struct Class\n",
+    "{\n",
+    "    explicit Class(int a)\n",
+    "    : a_ { a }\n",
+    "    { }\n",
+    "\n",
+    "    ~Class()\n",
+    "    {\n",
+    "        std::cout << \"Release object with value \" << a_ << '\\n';\n",
+    "    }\n",
+    "\n",
+    "    private:\n",
     "\n",
-    "* Use `release()` method:"
+    "    int a_ {};\n",
+    "};"
    ]
   },
   {
@@ -317,10 +336,11 @@
    "metadata": {},
    "outputs": [],
    "source": [
+    "#include <memory> \n",
+    "\n",
     "{\n",
-    "    auto ptr = std::make_unique<int>(5);\n",
-    "    ptr.release(); // Beware: `.` and not `->` as it is a method of the smart pointer class, not of the \n",
-    "                   // underlying class!\n",
+    "    auto ptr = std::make_unique<Class>(5);\n",
+    "    ptr = nullptr;\n",
     "}"
    ]
   },
@@ -328,7 +348,14 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "* Or assign `nullptr` to the pointer"
+    "#### Beware: `release()` doesn't do what you might think it does!"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "Smart pointer classes provide a `release()` method, but what they actually release is **ownership**, not memory."
    ]
   },
   {
@@ -338,8 +365,33 @@
    "outputs": [],
    "source": [
     "{\n",
-    "    auto ptr = std::make_unique<int>(5);\n",
-    "    ptr = nullptr;\n",
+    "    auto ptr = std::make_unique<Class>(5);\n",
+    "    Class* raw_ptr = ptr.release(); // Beware: `.` and not `->` as it is a method of the smart pointer class, not of the \n",
+    "                                    // underlying class!\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "As you can see, there are no call to the destructor: the role of `release()` is to release the ownership of the allocated memory to `raw_ptr`, which has now the **responsability** of freeing the memory. \n",
+    "\n",
+    "What we ought to do to properly clean-up memory is therefore to call `delete` function (see [here](../1-ProceduralProgramming/5-DynamicAllocation.ipynb#Heap-and-free-store) if you need a refreshed of memory allocation)."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "{\n",
+    "    auto ptr = std::make_unique<Class>(5);\n",
+    "    Class* raw_ptr = ptr.release(); // Beware: `.` and not `->` as it is a method of the smart pointer class, not of the \n",
+    "                                    // underlying class!\n",
+    "\n",
+    "    delete raw_ptr;\n",
     "}"
    ]
   },
@@ -365,6 +417,8 @@
     "\n",
     "{\n",
     "    std::shared_ptr<double> ptr = std::make_shared<double>(5.);\n",
+    "\n",
+    "    std::cout << \"Nptr = \" << ptr.use_count() << std::endl;\n",
     "    \n",
     "    auto ptr2 = ptr;\n",
     "    \n",