+ All Categories
Home > Technology > [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics

[OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics

Date post: 25-May-2015
Category:
Upload: andrey-upadyshev
View: 1,922 times
Download: 1 times
Share this document with a friend
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.
Popular Tags:
14
Andrey Upadyshev Hot C++11: Rvalue References And Move Semantics Licensed under a CC BY-SA 4.0 License. Version of 2015.03.26
Transcript
Page 1: [OLD VERSION, USE A NEW ONE] Hot C++11, Part 1: Rvalue References And Move Semantics

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

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

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

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

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

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

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

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

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

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

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

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

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

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


Recommended