1.. title:: clang-tidy - modernize-pass-by-value 2 3modernize-pass-by-value 4======================= 5 6With move semantics added to the language and the standard library updated with 7move constructors added for many types it is now interesting to take an 8argument directly by value, instead of by const-reference, and then copy. This 9check allows the compiler to take care of choosing the best way to construct 10the copy. 11 12The transformation is usually beneficial when the calling code passes an 13*rvalue* and assumes the move construction is a cheap operation. This short 14example illustrates how the construction of the value happens: 15 16.. code-block:: c++ 17 18 void foo(std::string s); 19 std::string get_str(); 20 21 void f(const std::string &str) { 22 foo(str); // lvalue -> copy construction 23 foo(get_str()); // prvalue -> move construction 24 } 25 26.. note:: 27 28 Currently, only constructors are transformed to make use of pass-by-value. 29 Contributions that handle other situations are welcome! 30 31 32Pass-by-value in constructors 33----------------------------- 34 35Replaces the uses of const-references constructor parameters that are copied 36into class fields. The parameter is then moved with `std::move()`. 37 38Since ``std::move()`` is a library function declared in `<utility>` it may be 39necessary to add this include. The check will add the include directive when 40necessary. 41 42.. code-block:: c++ 43 44 #include <string> 45 46 class Foo { 47 public: 48 - Foo(const std::string &Copied, const std::string &ReadOnly) 49 - : Copied(Copied), ReadOnly(ReadOnly) 50 + Foo(std::string Copied, const std::string &ReadOnly) 51 + : Copied(std::move(Copied)), ReadOnly(ReadOnly) 52 {} 53 54 private: 55 std::string Copied; 56 const std::string &ReadOnly; 57 }; 58 59 std::string get_cwd(); 60 61 void f(const std::string &Path) { 62 // The parameter corresponding to 'get_cwd()' is move-constructed. By 63 // using pass-by-value in the Foo constructor we managed to avoid a 64 // copy-construction. 65 Foo foo(get_cwd(), Path); 66 } 67 68 69If the parameter is used more than once no transformation is performed since 70moved objects have an undefined state. It means the following code will be left 71untouched: 72 73.. code-block:: c++ 74 75 #include <string> 76 77 void pass(const std::string &S); 78 79 struct Foo { 80 Foo(const std::string &S) : Str(S) { 81 pass(S); 82 } 83 84 std::string Str; 85 }; 86 87 88Known limitations 89^^^^^^^^^^^^^^^^^ 90 91A situation where the generated code can be wrong is when the object referenced 92is modified before the assignment in the init-list through a "hidden" reference. 93 94Example: 95 96.. code-block:: c++ 97 98 std::string s("foo"); 99 100 struct Base { 101 Base() { 102 s = "bar"; 103 } 104 }; 105 106 struct Derived : Base { 107 - Derived(const std::string &S) : Field(S) 108 + Derived(std::string S) : Field(std::move(S)) 109 { } 110 111 std::string Field; 112 }; 113 114 void f() { 115 - Derived d(s); // d.Field holds "bar" 116 + Derived d(s); // d.Field holds "foo" 117 } 118 119 120Note about delayed template parsing 121^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 122 123When delayed template parsing is enabled, constructors part of templated 124contexts; templated constructors, constructors in class templates, constructors 125of inner classes of template classes, etc., are not transformed. Delayed 126template parsing is enabled by default on Windows as a Microsoft extension: 127`Clang Compiler User’s Manual - Microsoft extensions`_. 128 129Delayed template parsing can be enabled using the `-fdelayed-template-parsing` 130flag and disabled using `-fno-delayed-template-parsing`. 131 132Example: 133 134.. code-block:: c++ 135 136 template <typename T> class C { 137 std::string S; 138 139 public: 140 = // using -fdelayed-template-parsing (default on Windows) 141 = C(const std::string &S) : S(S) {} 142 143 + // using -fno-delayed-template-parsing (default on non-Windows systems) 144 + C(std::string S) : S(std::move(S)) {} 145 }; 146 147.. _Clang Compiler User’s Manual - Microsoft extensions: https://clang.llvm.org/docs/UsersManual.html#microsoft-extensions 148 149.. seealso:: 150 151 For more information about the pass-by-value idiom, read: `Want Speed? Pass by Value`_. 152 153 .. _Want Speed? Pass by Value: https://web.archive.org/web/20140205194657/http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/ 154 155Options 156------- 157 158.. option:: IncludeStyle 159 160 A string specifying which include-style is used, `llvm` or `google`. Default 161 is `llvm`. 162 163.. option:: ValuesOnly 164 165 When `true`, the check only warns about copied parameters that are already 166 passed by value. Default is `false`. 167