|
| 1 | +\subsection[Init]{Initialization} |
| 2 | + |
| 3 | +\begin{frame}[fragile] |
| 4 | + \frametitle{Initialization} |
| 5 | + \begin{block}{Initialization} |
| 6 | + \begin{itemize} |
| 7 | + \item \href{https://imgur.com/3wlxtI0}{Obligatory meme} |
| 8 | + \pause |
| 9 | + \item And the following were even missing: |
| 10 | + \begin{itemize} |
| 11 | + \item ordered, unordered, and partially ordered initialization |
| 12 | + \item direct-non-list-initialization |
| 13 | + \item non-vacuous initialization |
| 14 | + \item See \href{https://twitter.com/timur_audio/status/1004017362381795329}{this tweet} |
| 15 | + \end{itemize} |
| 16 | + \item Most of this is for language lawyers |
| 17 | + \item In the following we will discuss some practical implications |
| 18 | + \end{itemize} |
| 19 | + \end{block} |
| 20 | +\end{frame} |
| 21 | + |
| 22 | +\begin{frame}[fragile] |
| 23 | + \frametitle{Initialization} |
| 24 | + \begin{block}{Initializing scalars} |
| 25 | + \begin{cppcode} |
| 26 | + int i(42); // direct initialization |
| 27 | + int i{42}; // direct list initialization (C++11) |
| 28 | + int i = 42; // copy initialization |
| 29 | + int i = {42}; // copy list initialization (C++11) |
| 30 | + \end{cppcode} |
| 31 | + \begin{itemize} |
| 32 | + \item All of the above have the same effect: \mintinline{cpp}{i == 42} |
| 33 | + \end{itemize} |
| 34 | + \end{block} |
| 35 | + \begin{block}{Narrowing conversions} |
| 36 | + \begin{cppcode} |
| 37 | + int i(42.3); // i == 42 |
| 38 | + int i{42.3}; // compilation error |
| 39 | + int i = 42.3; // i == 42 |
| 40 | + int i = {42.3}; // compilation error |
| 41 | + \end{cppcode} |
| 42 | + \begin{itemize} |
| 43 | + \item Braced initialization prevents narrowing conversions |
| 44 | + \end{itemize} |
| 45 | + \end{block} |
| 46 | +\end{frame} |
| 47 | + |
| 48 | +\begin{frame}[fragile,shrink=10] |
| 49 | + \frametitle{Initialization} |
| 50 | + \begin{block}{Initializing class types with constructors} |
| 51 | + \begin{cppcode} |
| 52 | + struct C { |
| 53 | + C(int i); |
| 54 | + C(int i, int j); |
| 55 | + }; |
| 56 | + |
| 57 | + C c(42); // calls C(42) |
| 58 | + C c{42}; // same |
| 59 | + C c = 42; // calls C(42) in C++17, before C(C(42)) |
| 60 | + C c = {42}; // same |
| 61 | + |
| 62 | + C c(1, 2); // calls C(1, 2) |
| 63 | + C c{1, 2}; // calls C(1, 2) |
| 64 | + C c = (1, 2); // calls C(2), comma operator |
| 65 | + C c = {1, 2}; // calls C(1, 2) in C++17, before C(C(1, 2)) |
| 66 | + |
| 67 | + C c(1.1, 2.2); // calls C(1, 2) |
| 68 | + C c{1.1, 2.2}; // compilation error |
| 69 | + \end{cppcode} |
| 70 | + \end{block} |
| 71 | +\end{frame} |
| 72 | + |
| 73 | +\begin{frame}[fragile,shrink=10] |
| 74 | + \frametitle{Initialization} |
| 75 | + \begin{block}{std::initializer\_list} |
| 76 | + \begin{cppcode} |
| 77 | + struct C { |
| 78 | + C(int i, int j); |
| 79 | + C(std::initializer_list<int> l); |
| 80 | + }; |
| 81 | + |
| 82 | + C c(1, 2); // calls C(1, 2) |
| 83 | + C c{1, 2}; // calls C(std::initializer_list<int>{1, 2}) |
| 84 | + C c = (1, 2); // calls C(2), comma operator, error |
| 85 | + C c = {1, 2}; // calls C(std::initializer_list<int>{1, 2}) |
| 86 | + \end{cppcode} |
| 87 | + \begin{itemize} |
| 88 | + \item A constructor with a \mintinline{cpp}{std::initializer_list} parameter takes precedence over other overloads. |
| 89 | + \end{itemize} |
| 90 | + \end{block} |
| 91 | + \begin{alertblock}{Beware} |
| 92 | + \begin{cppcode} |
| 93 | + std::vector<int> v1(4, 5); // {5, 5, 5, 5} |
| 94 | + std::vector<int> v2{4, 5}; // {4, 5} |
| 95 | + \end{cppcode} |
| 96 | + \end{alertblock} |
| 97 | +\end{frame} |
| 98 | + |
| 99 | +\begin{frame}[fragile] |
| 100 | + \frametitle{Initialization} |
| 101 | + \begin{block}{Type deduction} |
| 102 | + \begin{cppcode} |
| 103 | + auto i(42); // int |
| 104 | + auto i{42}; // C++11: std::initializer_list<int> |
| 105 | + // since C++14: int |
| 106 | + auto i = 42; // int |
| 107 | + auto i = {42}; // std::initializer_list<int> |
| 108 | + \end{cppcode} |
| 109 | + \end{block} |
| 110 | +\end{frame} |
| 111 | + |
| 112 | +\begin{frame}[fragile] |
| 113 | + \frametitlecpp[11]{Initialization} |
| 114 | + \begin{block}{Default initialization} |
| 115 | + \begin{cppcode*}{linenos=false} |
| 116 | + T t; |
| 117 | + \end{cppcode*} |
| 118 | + \begin{itemize} |
| 119 | + \item If \mintinline{cpp}{T} has a default constructor (including compiler generated), calls it |
| 120 | + \item Otherwise \mintinline{cpp}{t} is left uninitialized (undefined value) |
| 121 | + \item If \mintinline{cpp}{T} is an array, default initializes all members |
| 122 | + \end{itemize} |
| 123 | + \end{block} |
| 124 | +\end{frame} |
| 125 | + |
| 126 | +\begin{frame}[fragile] |
| 127 | + \frametitlecpp[11]{Initialization} |
| 128 | + \begin{block}{Value initialization} |
| 129 | + \begin{cppcode} |
| 130 | + T t{}; // value initialization |
| 131 | + T t = {}; // same |
| 132 | + f(T()); // passes value-initialized temporary |
| 133 | + f(T{}); // same |
| 134 | + T t(); // function declaration |
| 135 | + \end{cppcode} |
| 136 | + \begin{itemize} |
| 137 | + \item Basically zero-initializes \mintinline{cpp}{t} (or the temporary), unless \mintinline{cpp}{T} has a user defined constructor |
| 138 | + \item Details on \href{https://en.cppreference.com/w/cpp/language/value_initialization}{cppreference} |
| 139 | + \end{itemize} |
| 140 | + \end{block} |
| 141 | +\end{frame} |
| 142 | + |
| 143 | +\begin{frame}[fragile,shrink=10] |
| 144 | + \frametitlecpp[11]{Initialization} |
| 145 | + \begin{block}{Aggregate initialization} |
| 146 | + \begin{cppcode} |
| 147 | + struct S { int i; double d; }; |
| 148 | + |
| 149 | + S s{1, 2.3}; // s.i == 1, s.d == 2.3 |
| 150 | + S s = {1, 2.3}; // same |
| 151 | + S s{.i = 1, .d = 2.3} // same, designated init. (C++20) |
| 152 | + S s = {.i = 1, .d = 2.3} // same |
| 153 | + S s{1}; // s.i == 1, s.d == 0.0 |
| 154 | + S s = {1}; // same |
| 155 | + S s{.i = 1} // same (C++20) |
| 156 | + S s = {.i = 1} // same (C++20) |
| 157 | + S s{}; // value init, s.i == 0, s.d == 0.0 |
| 158 | + S s; // default init, undefined values |
| 159 | + \end{cppcode} |
| 160 | + \begin{itemize} |
| 161 | + \item An aggregate is a class with no constructors, only public base classes (\cpp17) and members, no virtual functions, no default member initializers (until \cpp14) |
| 162 | + \item Details on \href{https://en.cppreference.com/w/cpp/language/aggregate_initialization}{cppreference} |
| 163 | + \end{itemize} |
| 164 | + \end{block} |
| 165 | +\end{frame} |
| 166 | + |
| 167 | +\begin{frame}[fragile] |
| 168 | + \frametitlecpp[11]{Initialization} |
| 169 | + \begin{exampleblock}{Best practices} |
| 170 | + \begin{itemize} |
| 171 | + \item In generic code, for a generic type \mintinline{cpp}{T}: |
| 172 | + \begin{itemize} |
| 173 | + \item \mintinline{cpp}{T t;} performs the minimally necessary initialization |
| 174 | + \item \mintinline{cpp}{T t{};} performs full and deterministic initialization |
| 175 | + \end{itemize} |
| 176 | + \item Prefer \mintinline{cpp}{T t{};} over \mintinline{cpp}{T t; memset(&t, 0, sizeof(t));} |
| 177 | + \item Prefer braces over parentheses to avoid accidental narrowing conversions |
| 178 | + \begin{itemize} |
| 179 | + \item Unless \mintinline{cpp}{T} has a \mintinline{cpp}{std::initializer_list} constructor that you do not want to call! |
| 180 | + \item Be wary of \mintinline{cpp}{std::vector}! |
| 181 | + \end{itemize} |
| 182 | + \item The STL value initializes when creating new user objects |
| 183 | + \begin{itemize} |
| 184 | + \item E.g. \mintinline{cpp}{vec.resize(vec.size() + 10);} |
| 185 | + \end{itemize} |
| 186 | + \item Aggregates are very flexible. If your class does not need special initialization, make it an aggregate |
| 187 | + \end{itemize} |
| 188 | + \end{exampleblock} |
| 189 | +\end{frame} |
| 190 | + |
| 191 | +\begin{frame}[fragile] |
| 192 | + \frametitle{Initialization} |
| 193 | + \begin{block}{Further resources} |
| 194 | + \begin{itemize} |
| 195 | + \item \href{https://www.youtube.com/watch?v=7DTlWPgX6zs}{CppCon 2018: Nicolai Josuttis “The Nightmare of Initialization in C++”} |
| 196 | + \item \href{https://www.youtube.com/watch?v=ZfP4VAK21zc}{Initialization in modern C++ - Timur Doumler - Meeting C++ 2018} |
| 197 | + \end{itemize} |
| 198 | + \end{block} |
| 199 | +\end{frame} |
0 commit comments