Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 167 additions & 8 deletions talk/morelanguage/move.tex
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,146 @@
\end{frame}

\begin{frame}[fragile]
\frametitlecpp[11]{Move semantics}
\begin{block}{The idea}
\frametitlecpp[11]{Value categories}
\begin{block}{Lvalue (left value / locator value)}
\begin{itemize}
\item An expression is an lvalue
\begin{itemize}
\item If its evaluation determines identity of object/function
\item If the object is not expiring (``xvalue'')
\end{itemize}
\item Lvalues have a persistent address in memory
\item Lvalues can be assigned to unless \cppinline{const}
\end{itemize}
\end{block}
\begin{exampleblock}{Lvalue examples}
\begin{cppcode*}{}
int i;
int & j = i;
T t;
t.m = 5; // lvalue, because t is lvalue
++i; // returns underlying object
\end{cppcode*}
\end{exampleblock}
\end{frame}

\begin{frame}[fragile]
\frametitlecpp[11]{Value Categories}
\begin{block}{Rvalue}
\begin{itemize}
\item a new type of reference: rvalue reference
\item An expression is an rvalue when from these primary categories
\begin{itemize}
\item used for move semantic
\item denoted by \cppinline{&&}
\item ``pure rvalue'': Result of built-in operator; initalizer of object
\item ``xvalue'': Expiring value, resources can ``moved''
\end{itemize}
\item Has no persistent address in memory
\begin{itemize}
\item Cannot use the addressof operator
\end{itemize}
\item Cannot be used as left-hand operand of built-in assignments

\end{itemize}
\end{block}
\vspace{-6mm}
\begin{overprint}
\onslide<1>
\begin{exampleblock}{Examples for rvalues}
\begin{cppcode*}{}
i = 42; // 42 is pure rv
i = a + b; // a+b is pure rv
T t = T{}; // T{} is pure rv
i++; // Pure rv (post-increment returns temp.)
T{}.m; // m is expiring because T{} is pure rv
std::move(x); // Converts lvalue into xvalue
\end{cppcode*}
\end{exampleblock}
\onslide<2>
\begin{alertblock}{Things that don't compile with rvalues}
\begin{cppcode*}{}
a + b = 2; // Cannot assign to pure rv
&(a+b); // Cannot take address of pure rv
&i++; // Same, post-increment returns pure rv
T{}.m = 2; // cannot assign if m is built-in type
\end{cppcode*}
\end{alertblock}
\end{overprint}
\end{frame}

\begin{frame}[fragile]
\frametitlecpp[11]{Value Categories: Terminology}
\begin{block}{Source of confusion}
\begin{itemize}
\item The name ``rvalue'' originates from them \textit{mostly} being on right-hand side
\item But it denotes value categories of \emph{expressions}
\item Rvalues can be assigned to for non-builtin types
\end{itemize}
\end{block}

\begin{exampleblock}{Example: rvalue on left-hand side}
\begin{cppcode*}{}
struct T{
int m;
T& operator=(int i);
};
std::cout << (T{} = 5).m << "\n";
\end{cppcode*}
\end{exampleblock}

\begin{alertblock}{Not possible with built-in types}
\begin{cppcode*}{}
std::cout << (int{} = 5) << "\n"; // Error
\end{cppcode*}
\end{alertblock}
\end{frame}

\begin{frame}[fragile]
\frametitlecpp[11]{Rvalue References}
\begin{block}{New reference type: rvalue reference}
\begin{itemize}
\item Declared with \cppinline{T&&}
\item Does not bind to lvalues
\end{itemize}
\end{block}

\begin{exampleblock}{Binding rules}
\begin{columns}[onlytextwidth]
\begin{column}{0.45\textwidth}
Lvalues
\begin{cppcode*}{linenos=false}
T lv;
T & ref = lv;//OK
T && rvref = lv;//Error
T const& cr = lv;//OK
\end{cppcode*}
\end{column}
\hfil
\begin{column}{0.5\textwidth}
Rvalues
\begin{cppcode*}{linenos=false}

T & ref = T{};//Error
T && rvref = T{};//OK
T const& cr = T{};//OK
\end{cppcode*}
\end{column}
\end{columns}
\end{exampleblock}

\begin{exampleblock}{Overload resolution prefers rvalue reference}
\begin{cppcode*}{}
void f(T const &);
void f(T &&); // Selected, because one could move from T
f(T{});
\end{cppcode*}
\end{exampleblock}
\end{frame}

\begin{frame}[fragile]
\frametitlecpp[11]{Move semantics}
\begin{block}{The idea}
\begin{itemize}
\item use rvalue references to reuse resources
\item binds only to prvalues and xvalues
\item 2 new special member functions in every class:
\begin{description}
\item[a move constructor] similar to copy constructor
Expand Down Expand Up @@ -145,14 +277,14 @@
\end{itemize}
\item if no move semantic is implemented, copies will be performed
\item the language and STL understand move semantic
\item the compiler moves whenever possible
\item the compiler uses copy elision or moves whenever possible
\begin{itemize}
\item e.g.\ when passing temporaries or returning from a function
\end{itemize}
\end{itemize}
\end{block}
\pause
\begin{exampleblock}{Practically}
\begin{exampleblock}{Practically (in \cpp11)}
\begin{cppcode*}{}
T f() { T r; return r; } // move r out of f
T v = f(); // move returned (temporary) T into v
Expand Down Expand Up @@ -214,7 +346,7 @@
\item 1 swap less, separate copy assignment operator needed
\item former content of \cppinline{*this} destroyed with caller argument
\end{itemize}
\item swap, move constructor/assignment must be \cppinline{noexcept}
\item swap, move constructor/assignment must be \cppinline{noexcept}!
\end{itemize}
\end{block}
\end{frame}
Expand Down Expand Up @@ -267,6 +399,33 @@
\end{exampleblock}
\end{frame}

\begin{frame}[fragile,t]
\frametitlecpp[11]{Move semantics: Don't forget noexcept!}
\begin{alertblock}{Vector pessimisation when move constructor can throw}
\begin{itemize}
\item When a vector reallocates, it must copy/move all elements
\begin{itemize}
\item An exception during move can abort the relocation of elements
\item Some elements might have been moved, others in original place
\item Cannot recover from this state
\item Therefore, must copy all elements and destroy originals!
\end{itemize}
\item With \cppinline{noexcept}, the much faster move is used
\end{itemize}
\end{alertblock}
\begin{exampleblock}{}
\small
\begin{cppcode*}{}
struct Movable1 { Movable1(Movable1 &&other); };
struct Movable2 { Movable2(Movable2 &&other) noexcept; };
while (vector1.size() < 10000) {
vector1.push_back(Movable1{}); // Copies
vector2.push_back(Movable2{}); // Moves
}
\end{cppcode*}
\end{exampleblock}
\end{frame}

\begin{frame}[fragile]
\frametitlecpp[11]{Move Semantic}
\begin{exercise}{Move semantics}
Expand Down
Loading