llvm-capstone/clang-tools-extra/docs/PassByValueTransform.rst
Chandler Carruth d9063c46f5 Rename cpp11-migrate to clang-modernize.
There is no reason to expect this tool to be limited to C++11, it seems
very likely to be of on-going interest. It seems likely to be useful for
modernizing even as new libraries come out in TSes and other formats
than a complete standard. Fundamentally, we need something a bit more
general. After some discussion on the list, going with
'clang-modernize'.

I've tried to do a reasonably comprehensive job of fixing up the names,
but I may still have missed some. Feel free to poke me if you spot any
fallout here. Things I've tried reasonably hard to find and fix:

- cpp11-migrate -> clang-modernize
- Migrator -> Modernizer
- Clean up the introductory documentation that was C++11 specific.

I'll also point out that this tool continues to delight me. =] Also,
a huge thanks to those who have so carefully, thoroughly documented the
tool. The docs here are simply phenomenal. Every tool should be this
well documented. I hope I have updated the documentation reasonably
well, but I'm not very good at documentation, so review much
appreciated.

llvm-svn: 189960
2013-09-04 17:35:07 +00:00

166 lines
4.4 KiB
ReStructuredText
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

.. index:: Pass-By-Value Transform
=======================
Pass-By-Value Transform
=======================
The Pass-By-Value Transform makes use of the pass-by-value idiom when possible.
With move semantics added to the language and the standard library updated with
move constructors added for many types it is now interesting to take an argument
directly by value, instead of by const-reference, and then copy. This
transformation allows the compiler to take care of choosing the best way to
construct the copy.
The transformation is usually beneficial when the calling code passes an
*rvalue* and assumes the move construction is a cheap operation. This short
example illustrates how the construction of the value happens:
.. code-block:: c++
void foo(std::string s);
std::string get_str();
void f(const std::string &str) {
foo(str); // lvalue -> copy construction
foo(get_str()); // prvalue -> move construction
}
.. note::
Currently only constructors are transformed to make use of pass-by-value.
Contributions that handle other situations are welcome!
Pass-by-value in constructors
-----------------------------
Replaces the uses of const-references constructor parameters that are copied
into class fields. The parameter is then moved with `std::move()`.
Since `std::move()` is a library function declared in `<utility>` it may be
necessary to add this include. The transform will add the include directive when
necessary.
Example::
$ clang-modernize -pass-by-value ctor.cpp
**ctor.cpp**
.. code-block:: c++
#include <string>
class Foo {
public:
- Foo(const std::string &Copied, const std::string &ReadOnly)
- : Copied(Copied), ReadOnly(ReadOnly)
+ Foo(std::string Copied, const std::string &ReadOnly)
+ : Copied(std::move(Copied)), ReadOnly(ReadOnly)
{}
private:
std::string Copied;
const std::string &ReadOnly;
};
std::string get_cwd();
void f(const std::string &Path) {
// The parameter corresponding to 'get_cwd()' is move-constructed. By
// using pass-by-value in the Foo constructor we managed to avoid a
// copy-construction.
Foo foo(get_cwd(), Path);
}
If the parameter is used more than once no transformation is performed since
moved objects have an undefined state. It means the following code will be left
untouched:
.. code-block:: c++
#include <string>
void pass(const std::string &S);
struct Foo {
Foo(const std::string &S) : Str(S) {
pass(S);
}
std::string Str;
};
Risk
^^^^
This modification is considered **reasonably safe** (see :option:`-risk`
option).
A situation where the generated code can be wrong is when the object referenced
is modified before the assignment in the init-list through a "hidden" reference.
Example:
.. code-block:: c++
std::string s("foo");
struct Base {
Base() {
s = "bar";
}
};
struct Derived : Base {
- Derived(const std::string &S) : Field(S)
+ Derived(std::string S) : Field(std::move(S))
{ }
std::string Field;
};
void f() {
- Derived d(s); // d.Field holds "bar"
+ Derived d(s); // d.Field holds "foo"
}
Note about delayed template parsing
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When delayed template parsing is enabled, constructors part of templated
contexts; templated constructors, constructors in class templates, constructors
of inner classes of template classes, etc., are not transformed. Delayed
template parsing is enabled by default on Windows as a Microsoft extension:
`Clang Compiler Users Manual - Microsoft extensions`_.
Delayed template parsing can be enabled using the `-fdelayed-template-parsing`
flag and disabled using `-fno-delayed-template-parsing`.
Example:
.. code-block:: c++
template <typename T> class C {
std::string S;
public:
= // using -fdelayed-template-parsing (default on Windows)
= C(const std::string &S) : S(S) {}
+ // using -fno-delayed-template-parsing (default on non-Windows systems)
+ C(std::string S) : S(std::move(S)) {}
};
.. _Clang Compiler Users Manual - Microsoft extensions: http://clang.llvm.org/docs/UsersManual.html#microsoft-extensions
.. seealso::
For more information about the pass-by-value idiom, read: `Want Speed? Pass by Value`_.
.. _Want Speed? Pass by Value: http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/