[old version, use a new one] hot c++11, part 1: rvalue references and move semantics
DESCRIPTION
New extended version of this slides: http://www.slideshare.net/oliora/hot-c-rvalue-references-and-move-semantics The slides for my mini-lecture "Hot C++11: Rvalue References And Move Semantics" that I've done for my colleagues in the company I'm working at. Note that the slides without the lecture itself can be not clear enough.TRANSCRIPT
![Page 1: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics](https://reader033.vdocuments.us/reader033/viewer/2022052900/556263e1d8b42ae87d8b4ef6/html5/thumbnails/1.jpg)
Andrey Upadyshev
Hot C++11:Rvalue References And Move Semantics
Licensed under a CC BY-SA 4.0 License. Version of 2015.03.26
![Page 2: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics](https://reader033.vdocuments.us/reader033/viewer/2022052900/556263e1d8b42ae87d8b4ef6/html5/thumbnails/2.jpg)
Lvalue And Rvalue (how comes from C)
• lvalue - may appear on the left or on the right hand side of an assignment!
• rvalue - can only appear on the right hand side of an assignment
2
![Page 3: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics](https://reader033.vdocuments.us/reader033/viewer/2022052900/556263e1d8b42ae87d8b4ef6/html5/thumbnails/3.jpg)
Lvalue And Rvalue, Example 1int a = 42; // ok lvalue on left side of assignment int b = 43; // and rvalue on right side !a = b; // ok, lvalue may be on any side of assignment b = a; // ok, lvalue may be on any side of assignment !int c = a * b; // ok, rvalue on right side of assignment a * b = 42; // error, rvalue on left hand side of assignment
3
![Page 4: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics](https://reader033.vdocuments.us/reader033/viewer/2022052900/556263e1d8b42ae87d8b4ef6/html5/thumbnails/4.jpg)
Lvalue And Rvalue (C++ style)• lvalue - locator value: refers to a defined region of
storage (possible to get address of)!
• rvalue - is an expression that is not an lvalue!
• rvalue - is expression resulting to temporary object
4
![Page 5: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics](https://reader033.vdocuments.us/reader033/viewer/2022052900/556263e1d8b42ae87d8b4ef6/html5/thumbnails/5.jpg)
Lvalue And Rvalue, Example 2int i = 42; int *p = &i; // ok, i is an lvalue int *p1 = &43; // error, cannot take the address of an rvalue !int& foo() { ... } foo() = 42; // ok, foo() is an lvalue int *p2 = &foo(); // ok, foo() is an lvalue !int bar() { ... } int i = bar(); // ok, foobar() is an rvalue bar() = 42; // error, cannot assign to an rvalue int *p3 = &bar(); // error, cannot take the address of an rvalue
5
![Page 6: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics](https://reader033.vdocuments.us/reader033/viewer/2022052900/556263e1d8b42ae87d8b4ef6/html5/thumbnails/6.jpg)
Rvalue Referencevoid foo(const Bar& bar); ! Can not modify bar. Accepts lvalue and rvalue.!
void foo(Bar& bar); ! Can modify bar. Accepts lvalue only (Visual Studio also accepts rvalue. But this does not conform the Standard)!
void foo(Bar&& bar); ! Can modify bar. Accepts rvalue only. Takes precedence over Bar& and const Bar& overloads.!
void foo(const Bar&& bar); ! Allowed but has no useful meaning. Use const Bar& instead.
6
![Page 7: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics](https://reader033.vdocuments.us/reader033/viewer/2022052900/556263e1d8b42ae87d8b4ef6/html5/thumbnails/7.jpg)
Move Semantics In Example
Copying!MemBuf a = ...;MemBuf b(a);
Copy ctor: MemBuf(const MemBuf& op);
7
class MemBuf { void *m_data; size_t m_size; ... };
Similar reasoning applies to the copy/move assignment.
F1 23 4C DB 98 73 11 ...a.m_data = addr1 a.m_size = n
b.m_data = addr2 b.m_size = n// a is not changed
allocate and copy
F1 23 4C DB 98 73 11 ...
Moving!MemBuf a = ...;MemBuf b(std::move(a));
Move ctor: MemBuf(MemBuf&& op);
F1 23 4C DB 98 73 11 ...a.m_data = addr1 a.m_size = n
b.m_data = addr1 b.m_size = na.m_data = nullptr a.m_size = 0
Note that "cleared out" object must stay in
consistent state}
![Page 8: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics](https://reader033.vdocuments.us/reader033/viewer/2022052900/556263e1d8b42ae87d8b4ef6/html5/thumbnails/8.jpg)
Why Move Semantics?Useful for:!A. Better performance for classes with expensive
copy (like STL containers):!void push_back(const string& s); // copies s void push_back(string&& s); // moves s (no copy)
B. Clearer interface working with non-copyable objects (like files, threads etc):!
std::auto_ptr<File> openFile(filename); File openFile(filename);
8
![Page 9: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics](https://reader033.vdocuments.us/reader033/viewer/2022052900/556263e1d8b42ae87d8b4ef6/html5/thumbnails/9.jpg)
Forcing Move SemanticsX a, b; std::swap(a, b); !template<class T> void std::swap(T& a, T& b) { T tmp(a); a = b; b = tmp; } !template<class T> void std::swap(T& a, T& b) { T tmp(std::move(a)); a = std::move(b); b = std::move(tmp); }
Three copying (C++98)
Three movings, no copying!(C++11, enabled only if T is movable)
std::move does not move any data but casts lvalue to rvalue => forces move semantics
9
![Page 10: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics](https://reader033.vdocuments.us/reader033/viewer/2022052900/556263e1d8b42ae87d8b4ef6/html5/thumbnails/10.jpg)
Rvalue Reference Is Not Rvaluevoid foo1(Bar&& arg) { Bar b = arg; // arg copied. arg is a named var so it's lvalue not rvalue } !void foo2(Bar&& arg) { Bar b = std::move(arg); // arg moved (move semantics forced) } !class Foo3 { Bar m_b; Foo3(Foo3&& arg) : m_b(arg.m_b) // arg.m_b copied. arg is a named var so it's lvalue not rvalue! {} };!!class Foo4 { Bar m_b; Foo4(Foo4&& arg) : m_b(std::move(arg.m_b)) // arg.m_b moved (move semantics forced), or! : m_b(std::move(arg).m_b) // arg.m_b moved (move semantics forced & member of rvalue is rvalue) {} };
10
![Page 11: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics](https://reader033.vdocuments.us/reader033/viewer/2022052900/556263e1d8b42ae87d8b4ef6/html5/thumbnails/11.jpg)
Move Semantics and RVOclass Foo {...}; // Assume Foo is movable!!Foo bar1() { Foo r; return std::move(r); // RVO blocked => r is moved. OK but could be better}!Foo bar2() { Foo r; return r; // RVO used => perfect}!class Bar {...}; // Assume Bar is movable and Foo has ctor Foo(Bar&&)!Foo bar3() { Bar tmp; return tmp; // No RVO for tmp (because tmp is not Foo). It actually returns Foo(tmp) => tmp is copied!}!Foo bar4() { Bar tmp; return std::move(tmp); // No RVO. It actually returns Foo(std::move(tmp)) => moving is the best we can get}
11
![Page 12: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics](https://reader033.vdocuments.us/reader033/viewer/2022052900/556263e1d8b42ae87d8b4ef6/html5/thumbnails/12.jpg)
Move Semantics And Exception SafetyFor good reason STL containers may copy elements internally unless ones' move constructor doesn't throw, check:!
• std::move_if_noexcept • std::is_nothrow_move_constructible
To optimize, just add noexcept (only if function really doesn't throw, no cheating, please!):!
Foo::Foo(Foo&& arg) noexcept;!
Note that it is not supported in Visual Studio before 2015, use macro like BOOST_NOEXCEPT (<boost/config/suffix.hpp>):!
Foo::Foo(Foo&& arg) BOOST_NOEXCEPT;
12
![Page 13: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics](https://reader033.vdocuments.us/reader033/viewer/2022052900/556263e1d8b42ae87d8b4ef6/html5/thumbnails/13.jpg)
Compiler-Generated Functions• Compiler can generate move constructor and move assignment operator!
• Not generated if explicitly declared either one of:!• destructor!• copy constructor!• copy assignment operator!• move constructor!• move assignment operator!
• Change from C++98: copy constructor and copy assignment operator aren't generated if move constructor or move assignment operator is explicitly declared!
• Not supported before Visual Studio 2014 CTP3
rule of five
13
}
![Page 14: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics](https://reader033.vdocuments.us/reader033/viewer/2022052900/556263e1d8b42ae87d8b4ef6/html5/thumbnails/14.jpg)
Useful LinksAlex Allain, Move semantics and rvalue references in C++11http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html!
Dave Abrahams, Exceptionally Moving! http://web.archive.org/web/20130524084627/http://cpp-next.com/archive/2009/10/exceptionally-moving/!
Move constructors http://en.cppreference.com/w/cpp/language/move_constructor!
C++11 Standard (final plus minor editorial changes)!http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
14