Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion talk/basicconcepts/functions.tex
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@
struct T {...}; T a;
void fVal(T value); fVal(a); // by value
void fRef(const T &value); fRef(a); // by reference
void fPtr(const T *value); fPtr(|{\setlength{\fboxsep}{0pt}\color{gray}\colorbox{yellow}{\textsc{&}}}|a); // by pointer
void fPtr(const T *value); fPtr(&a); // by pointer
void fWrite(T &value); fWrite(a); // non-const ref
\end{cppcode*}
\end{block}
Expand Down
173 changes: 165 additions & 8 deletions talk/morelanguage/move.tex
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,145 @@
\end{frame}

\begin{frame}[fragile]
\frametitlecpp[11]{Move semantics}
\begin{block}{The idea}
\frametitlecpp[11]{Move semantics: 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]{Move semantics: 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; initialiser 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]{Move semantics: 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]{Move semantics: 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. Enables move
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 2 new special member functions in every class:
\begin{description}
\item[a move constructor] similar to copy constructor
Expand Down Expand Up @@ -145,14 +276,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 +345,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 +398,32 @@
\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 aborts the relocation of elements
\item Move might not be revertible, so vector falls back to copy
\item This can significantly slow down the resize operation
\end{itemize}
\item With \cppinline{noexcept}, the much faster move is used
\end{itemize}
\end{alertblock}
\begin{exampleblock}{Vector resize with copy/move}
\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
2 changes: 1 addition & 1 deletion talk/morelanguage/raii.tex
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@
% escapeinside seems to break gobble, so need to un-indent manually
\begin{cppcode*}{escapeinside=@@}
auto shared = std::make_shared<int>(100);
auto print = [@\textcolor{red}{&}@shared](){
auto print = [@\textcolor{red}{\&}@shared](){
std::cout << "Use: " << shared.use_count() << " "
<< "value: " << *shared << "\n";
};
Expand Down