143
MOVE SEMANTICS C++11/14 JOSE CAICOYA

MOVE SEMANTICS C++11/14 fileIndex • Non copyable classes • lvalue and rvalue references • move constructor and move operator • std::move • std::forward • The End

  • Upload
    buinhi

  • View
    231

  • Download
    4

Embed Size (px)

Citation preview

MOVE SEMANTICS C++11/14

JOSE CAICOYA

UNDERSTAND and USE MOVE SEMANTICS

Pourpose

Index• Non copyable classes

• lvalue and rvalue references

• move constructor and move operator

• std::move

• std::forward

• The End

1. Non copyable classes

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass HiddenStruct { public: HiddenStruct() : _value(0) {} int getValue() const noexcept {return _value;} void setValue(int value) noexcept {_value = value;} static HiddenStruct Factory() { HiddenStruct hs; hs.setValue(1); return hs; }

private: int _value; };

static inline std::ostream & operator<<(std::ostream & out, const HiddenStruct &hs) { return out << "[VALUE:" << hs.getValue() << ']'; }

static void HiddenStructFactoryExecution() { HiddenStruct hs = HiddenStruct::Factory(); std::cout << "HiddenStruct built: " << hs << std::endl; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass HiddenStruct { public: HiddenStruct() : _value(0) {} int getValue() const noexcept {return _value;} void setValue(int value) noexcept {_value = value;} static HiddenStruct Factory() { HiddenStruct hs; hs.setValue(1); return hs; }

private: int _value; };

static inline std::ostream & operator<<(std::ostream & out, const HiddenStruct &hs) { return out << "[VALUE:" << hs.getValue() << ']'; }

static void HiddenStructFactoryExecution() { HiddenStruct hs = HiddenStruct::Factory(); std::cout << "HiddenStruct built: " << hs << std::endl; }

HiddenStruct built: [VALUE:1]

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILER

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

class NonModifiable { public: explicit NonModifiable(int value) : _value(value) {} int getValue() const noexcept {return _value;} static NonModifiable Factory() {return NonModifiable(2);} private: int _value; };

static inline std::ostream & operator<<(std::ostream &out, const NonModifiable &nm) { return out << "[VALUE:" << nm.getValue() << ']'; }

static void NonModifiableFactoryExecution() { NonModifiable nm = NonModifiable::Factory(); std::cout << "NonModifiable built: " << nm << std::endl; }

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass NonModifiable { public: explicit NonModifiable(int value) : _value(value) {} int getValue() const noexcept {return _value;} static NonModifiable Factory() {return NonModifiable(2);} private: int _value; };

static inline std::ostream & operator<<(std::ostream &out, const NonModifiable &nm) { return out << "[VALUE:" << nm.getValue() << ']'; }

static void NonModifiableFactoryExecution() { NonModifiable nm = NonModifiable::Factory(); std::cout << "NonModifiable built: " << nm << std::endl; }

NonModifiable built: [VALUE:2]

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass NonCopyable { public: explicit NonCopyable(int value) : _value(value) {} NonCopyable(const NonCopyable &) = delete; NonCopyable & operator=(const NonCopyable &) = delete; int getValue() const noexcept {return _value;} void setValue(int value) noexcept {_value = value;} static NonCopyable Factory() {return NonCopyable(3);} private: int _value; };

static inline std::ostream & operator<<(std::ostream &out, const NonCopyable &nc) { return out << "[VALUE:" << nc.getValue() << ']'; }

static void NonCopyableFactoryExecution() { NonCopyable nc = NonCopyable::Factory(); std::cout << "NonCopyable built: " << nc << std::endl; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass NonCopyable { public: explicit NonCopyable(int value) : _value(value) {} NonCopyable(const NonCopyable &) = delete; NonCopyable & operator=(const NonCopyable &) = delete; int getValue() const noexcept {return _value;} void setValue(int value) noexcept {_value = value;} static NonCopyable Factory() {return NonCopyable(3);} private: int _value; };

static inline std::ostream & operator<<(std::ostream &out, const NonCopyable &nc) { return out << "[VALUE:" << nc.getValue() << ']'; }

static void NonCopyableFactoryExecution() { NonCopyable nc = NonCopyable::Factory(); std::cout << "NonCopyable built: " << nc << std::endl; }

Call to deleted constructor of ‘NonCopyable’

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass NonCopyable { public: explicit NonCopyable(int value) : _value(value) {} NonCopyable(const NonCopyable &) = delete; NonCopyable & operator=(const NonCopyable &) = delete; int getValue() const noexcept {return _value;} void setValue(int value) noexcept {_value = value;} static NonCopyable * RawPointerFactory() {return new NonCopyable(3);} private: int _value; };

static inline std::ostream & operator<<(std::ostream &out, const NonCopyable &nc) { return out << "[VALUE:" << nc.getValue() << ']'; }

static void NonCopyableRawPointerFactoryExecution() { NonCopyable *nonCopyableRP = NonCopyable::RawPointerFactory(); std::cout << "NonCopyable raw pointer built: " << *nonCopyableRP << std::endl; delete nonCopyableRP; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass NonCopyable { public: explicit NonCopyable(int value) : _value(value) {} NonCopyable(const NonCopyable &) = delete; NonCopyable & operator=(const NonCopyable &) = delete; int getValue() const noexcept {return _value;} void setValue(int value) noexcept {_value = value;} static NonCopyable * RawPointerFactory() {return new NonCopyable(3);} private: int _value; };

static inline std::ostream & operator<<(std::ostream &out, const NonCopyable &nc) { return out << "[VALUE:" << nc.getValue() << ']'; }

static void NonCopyableRawPointerFactoryExecution() { NonCopyable *nonCopyableRP = NonCopyable::RawPointerFactory(); std::cout << "NonCopyable raw pointer built: " << *nonCopyableRP << std::endl; delete nonCopyableRP; }

NonCopyable raw pointer built: [VALUE:3]

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass NonCopyable { public: explicit NonCopyable(int value) : _value(value) {} NonCopyable(const NonCopyable &) = delete; NonCopyable & operator=(const NonCopyable &) = delete; int getValue() const noexcept {return _value;} void setValue(int value) noexcept {_value = value;} static std::shared_ptr<NonCopyable> SharedPtrFactory() { return std::make_shared<NonCopyable>(3); } private: int _value; };

static inline std::ostream & operator<<(std::ostream &out, const NonCopyable &nc) { return out << "[VALUE:" << nc.getValue() << ']'; }

static void NonCopyableSharedPtrFactoryExecution() { std::shared_ptr<NonCopyable> nonCopyableSP = NonCopyable::SharedPtrFactory(); std::cout << "NonCopybale shared pointer built: " << *nonCopyableSP << std::endl; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass NonCopyable { public: explicit NonCopyable(int value) : _value(value) {} NonCopyable(const NonCopyable &) = delete; NonCopyable & operator=(const NonCopyable &) = delete; int getValue() const noexcept {return _value;} void setValue(int value) noexcept {_value = value;} static std::shared_ptr<NonCopyable> SharedPtrFactory() { return std::make_shared<NonCopyable>(3); } private: int _value; };

static inline std::ostream & operator<<(std::ostream &out, const NonCopyable &nc) { return out << "[VALUE:" << nc.getValue() << ']'; }

static void NonCopyableSharedPtrFactoryExecution() { std::shared_ptr<NonCopyable> nonCopyableSP = NonCopyable::SharedPtrFactory(); std::cout << "NonCopybale shared pointer built: " << *nonCopyableSP << std::endl; }

NonCopybale shared pointer built: [VALUE:3]

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass NonCopyable { public: explicit NonCopyable(int value) : _value(value) {} NonCopyable(const NonCopyable &) = delete; NonCopyable & operator=(const NonCopyable &) = delete; int getValue() const noexcept {return _value;} void setValue(int value) noexcept {_value = value;} static std::shared_ptr<NonCopyable> SharedPtrFactory() { return std::make_shared<NonCopyable>(3); } void swap(NonCopyable &rhs) { int aux = _value; _value = rhs._value; rhs._value = aux; } private: int _value; };

static inline std::ostream & operator<<(std::ostream &out, const NonCopyable &nc) { return out << "[VALUE:" << nc.getValue() << ']'; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

272829 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

COMPILER

static inline std::ostream & operator<<(std::ostream &out, const NonCopyable &nc) { return out << "[VALUE:" << nc.getValue() << ']'; }

static void NonCopyableSwapFactoryExecution() { std::shared_ptr<NonCopyable> nonCopyableSP = NonCopyable::SharedPtrFactory(); NonCopyable nc(0); std::cout << "shared pointer: " << *nonCopyableSP << ", nc: " << nc << std::endl; nc.swap(*nonCopyableSP); std::cout << "After swap:\nshared pointer: " << *nonCopyableSP << ", nc: " << nc << std::endl; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

272829 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

COMPILER

static inline std::ostream & operator<<(std::ostream &out, const NonCopyable &nc) { return out << "[VALUE:" << nc.getValue() << ']'; }

static void NonCopyableSwapFactoryExecution() { std::shared_ptr<NonCopyable> nonCopyableSP = NonCopyable::SharedPtrFactory(); NonCopyable nc(0); std::cout << "shared pointer: " << *nonCopyableSP << ", nc: " << nc << std::endl; nc.swap(*nonCopyableSP); std::cout << "After swap:\nshared pointer: " << *nonCopyableSP << ", nc: " << nc << std::endl; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

shared pointer: [VALUE:3], nc: [VALUE:0] After swap: shared pointer: [VALUE:0], nc: [VALUE:3]

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass NonCopyable { public: explicit NonCopyable(int value) : _value (value) {} NonCopyable(const NonCopyable &) = delete; NonCopyable & operator=(const NonCopyable &) = delete; int getValue() const noexcept {return _value;} void setValue(int value) noexcept {_value = value;} static NonCopyable Factory() {return NonCopyable(3);} NonCopyable(NonCopyable &&rhsRef) = default; NonCopyable & operator=(NonCopyable &&rhsRef) = default; private: int _value; };

static inline std::ostream & operator<<(std::ostream &out, const NonCopyable &nc) { return out << "[VALUE:" << nc.getValue() << ']'; }

static void NonCopyableMoveFactoryExecution() { NonCopyable nc = NonCopyable::Factory(); std::cout << "NonCopybale nc: " << nc << std::endl; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass NonCopyable { public: explicit NonCopyable(int value) : _value (value) {} NonCopyable(const NonCopyable &) = delete; NonCopyable & operator=(const NonCopyable &) = delete; int getValue() const noexcept {return _value;} void setValue(int value) noexcept {_value = value;} static NonCopyable Factory() {return NonCopyable(3);} NonCopyable(NonCopyable &&rhsRef) = default; NonCopyable & operator=(NonCopyable &&rhsRef) = default; private: int _value; };

static inline std::ostream & operator<<(std::ostream &out, const NonCopyable &nc) { return out << "[VALUE:" << nc.getValue() << ']'; }

static void NonCopyableMoveFactoryExecution() { NonCopyable nc = NonCopyable::Factory(); std::cout << "NonCopybale nc: " << nc << std::endl; }

Option: NonCopybale nc: [VALUE:3]

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

2. lvalue and rvalue references

THEORY

lvalues are generally things you can take the address of

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

lvalues are generally things you can take the address of

rvalues are generally things you can’t take the address of

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

A reference type that is declared using& is called a lvalue reference

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

A reference type that is declared using& is called a lvalue reference

A reference type that is declared using && is called a rvalue reference

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

rvalue references identify objects that may be moved from

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

std::cout << Classifier::WhatIs(3) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

std::cout << Classifier::WhatIs(3) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; std::cout << Classifier::WhatIs(ii) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; std::cout << Classifier::WhatIs(ii) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; int *iiPtr = &ii; std::cout << Classifier::WhatIs(iiPtr) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; int *iiPtr = &ii; std::cout << Classifier::WhatIs(iiPtr) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; int *iiPtr = &ii; std::cout << Classifier::WhatIs(*iiPtr) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; int *iiPtr = &ii; std::cout << Classifier::WhatIs(*iiPtr) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; int &iiRef = ii; std::cout << Classifier::WhatIs(iiRef) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; int &iiRef = ii; std::cout << Classifier::WhatIs(iiRef) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int &&iiRefRef = 3; std::cout << Classifier::WhatIs(iiRefRef) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int &&iiRefRef = 3; std::cout << Classifier::WhatIs(iiRefRef) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; int &&iiRefRef = ii; std::cout << Classifier::WhatIs(iiRefRef) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; int &&iiRefRef = ii; std::cout << Classifier::WhatIs(iiRefRef) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int trivialFoo(int value) { return value + 1; }

std::cout << Classifier::WhatIs(trivialFoo(3)) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int trivialFoo(int value) { return value + 1; }

std::cout << Classifier::WhatIs(trivialFoo(3)) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

3. move ctor. & optor.

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass NonCopyable { public: explicit NonCopyable(int value) : _value (value) {} NonCopyable(const NonCopyable &) = delete; NonCopyable & operator=(const NonCopyable &) = delete; int getValue() const noexcept {return _value;} void setValue(int value) noexcept {_value = value;} static NonCopyable Factory() {return NonCopyable(3);} NonCopyable(NonCopyable &&rhsRef) = default; NonCopyable & operator=(NonCopyable &&rhsRef) = default; private: int _value; };

static inline std::ostream & operator<<(std::ostream &out, const NonCopyable &nc) { return out << "[VALUE:" << nc.getValue() << ']'; }

static void NonCopyableMoveFactoryExecution() { NonCopyable nc = NonCopyable::Factory(); std::cout << "NonCopybale nc: " << nc << std::endl; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Inner { public: Inner() { std::cout << "Inner class ctor - "; } Inner(const Inner &rhs) { std::cout << "Inner class copy ctor - "; } Inner & operator=(const Inner &rhs) { if(this != &rhs) std::cout << "Inner class copy optor - "; return *this; } Inner(Inner &&rhsRef) { std::cout << "Inner class move ctor - "; } Inner & operator=(Inner &&rhsRef) { if(this != &rhsRef) std::cout << "Inner class move optor - "; return *this; } ~Inner() { std::cout << " - Inner class dtor\n"; } };

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Outer { public: Outer() : _inner() { std::cout << "Outer class ctor\n"; } Outer(const Outer &rhs) : _inner(rhs._inner) { std::cout << "Outer class copy ctor\n"; } Outer & operator=(const Outer &rhs) { if(this != &rhs) { _inner = rhs._inner; std::cout << "Outer class copy optor\n"; } return *this;} Outer(Outer &&rhsRef) : _inner(rhsRef._inner) { std::cout << "Outer class move ctor\n"; } Outer & operator=(Outer &&rhsRef) { if(this != &rhsRef) { _inner = rhsRef._inner; std::cout << "Outer class move optor\n"; } return *this; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 64 66 67 68 69 70

COMPILER virtual ~Outer() { std::cout << "Outer class dtor"; } static Outer Factory() { return Outer(); } private: Inner _inner; };

static void OuterFactoryExecution() { Outer::Factory(); }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 64 66 67 68 69 70

COMPILER virtual ~Outer() { std::cout << "Outer class dtor"; } static Outer Factory() { return Outer(); } private: Inner _inner; };

static void OuterFactoryExecution() { Outer::Factory(); }

Inner class ctor - Outer class ctor Inner class copy ctor - Outer class move ctor Outer class dtor - Inner class dtor Outer class dtor - Inner class dtor

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 64 66 67 68 69 70

COMPILER virtual ~Outer() { std::cout << "Outer class dtor"; } static Outer Factory() { return Outer(); } private: Inner _inner; };

static void OuterFactoryExecution() { Outer::Factory(); }

Inner class ctor - Outer class ctor Inner class copy ctor - Outer class move ctor Outer class dtor - Inner class dtor Outer class dtor - Inner class dtor

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Outer { public: Outer() : _inner() { std::cout << "Outer class ctor\n"; } Outer(const Outer &rhs) : _inner(rhs._inner) { std::cout << "Outer class copy ctor\n"; } Outer & operator=(const Outer &rhs) { if(this != &rhs) { _inner = rhs._inner; std::cout << "Outer class copy optor\n"; } return *this;} Outer(Outer &&rhsRef) : _inner(rhsRef._inner) { std::cout << "Outer class move ctor\n"; } Outer & operator=(Outer &&rhsRef) { if(this != &rhsRef) { _inner = rhsRef._inner; std::cout << "Outer class move optor\n"; } return *this; }

Inner class ctor - Outer class ctor Inner class copy ctor - Outer class move ctor Outer class dtor - Inner class dtor Outer class dtor - Inner class dtor

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Outer { public: Outer() : _inner() { std::cout << "Outer class ctor\n"; } Outer(const Outer &rhs) : _inner(rhs._inner) { std::cout << "Outer class copy ctor\n"; } Outer & operator=(const Outer &rhs) { if(this != &rhs) { _inner = rhs._inner; std::cout << "Outer class copy optor\n"; } return *this;} Outer(Outer &&rhsRef) : _inner(rhsRef._inner) { std::cout << "Outer class move ctor\n"; } Outer & operator=(Outer &&rhsRef) { if(this != &rhsRef) { _inner = rhsRef._inner; std::cout << "Outer class move optor\n"; } return *this; }

Inner class ctor - Outer class ctor Inner class copy ctor - Outer class move ctor Outer class dtor - Inner class dtor Outer class dtor - Inner class dtor

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Outer { public: Outer() : _inner() { std::cout << "Outer class ctor\n"; } Outer(const Outer &rhs) : _inner(rhs._inner) { std::cout << "Outer class copy ctor\n"; } Outer & operator=(const Outer &rhs) { if(this != &rhs) { _inner = rhs._inner; std::cout << "Outer class copy optor\n"; } return *this;} Outer(Outer &&rhsRef) : _inner(std::move(rhsRef._inner)) { std::cout << "Outer class move ctor\n"; } Outer & operator=(Outer &&rhsRef) { if(this != &rhsRef) { _inner = rhsRef._inner; std::cout << "Outer class move optor\n"; } return *this; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Outer { public: Outer() : _inner() { std::cout << "Outer class ctor\n"; } Outer(const Outer &rhs) : _inner(rhs._inner) { std::cout << "Outer class copy ctor\n"; } Outer & operator=(const Outer &rhs) { if(this != &rhs) { _inner = rhs._inner; std::cout << "Outer class copy optor\n"; } return *this;} Outer(Outer &&rhsRef) : _inner(std::move(rhsRef._inner)) { std::cout << "Outer class move ctor\n"; } Outer & operator=(Outer &&rhsRef) { if(this != &rhsRef) { _inner = rhsRef._inner; std::cout << "Outer class move optor\n"; } return *this; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Outer { public: Outer() : _inner() { std::cout << "Outer class ctor\n"; } Outer(const Outer &rhs) : _inner(rhs._inner) { std::cout << "Outer class copy ctor\n"; } Outer & operator=(const Outer &rhs) { if(this != &rhs) { _inner = rhs._inner; std::cout << "Outer class copy optor\n"; } return *this;} Outer(Outer &&rhsRef) : _inner(std::move(rhsRef._inner)) { std::cout << "Outer class move ctor\n"; } Outer & operator=(Outer &&rhsRef) { if(this != &rhsRef) { _inner = std::move(rhsRef._inner); std::cout << "Outer class move optor\n"; } return *this; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Outer { public: Outer() : _inner() { std::cout << "Outer class ctor\n"; } Outer(const Outer &rhs) : _inner(rhs._inner) { std::cout << "Outer class copy ctor\n"; } Outer & operator=(const Outer &rhs) { if(this != &rhs) { _inner = rhs._inner; std::cout << "Outer class copy optor\n"; } return *this;} Outer(Outer &&rhsRef) : _inner(std::move(rhsRef._inner)) { std::cout << "Outer class move ctor\n"; } Outer & operator=(Outer &&rhsRef) { if(this != &rhsRef) { _inner = std::move(rhsRef._inner); std::cout << "Outer class move optor\n"; } return *this; }

Inner class ctor - Outer class ctor Inner class move ctor - Outer class move ctor Outer class dtor - Inner class dtor Outer class dtor - Inner class dtor

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Base { public: Base() { std::cout << "Base class ctor - "; } Base(const Base &rhs) { std::cout << "Base class copy ctor - "; } Base & operator=(const Base &rhs) { if(this != &rhs) std::cout << "Base class copy optor - "; return *this; } Base(Base &&rhsRef) { std::cout << "Base class move ctor - "; } Base & operator=(Base &&rhsRef) { if(this != &rhsRef) std::cout << "Base class move optor - "; return *this; } ~Base() { std::cout << " - Base class dtor\n"; } };

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Derived: public Base { public: Derived() : Base() { std::cout << "Derived class ctor\n"; } Derived(const Derived &rhs) : Base(rhs) { std::cout << "Derived class copy ctor\n"; } Derived & operator=(const Derived &rhs) { if(this != &rhs) { Base::operator=(rhs); std::cout << "Derived class copy optor\n"; } return *this;} Derived(Derived &&rhsRef) : Base(std::move(rhsRef)) { std::cout << "Derived class move ctor\n"; } Derived & operator=(Derived &&rhsRef) { if(this != &rhsRef) { Base::operator=(std::move(rhsRef)); std::cout << "Derived class move optor\n"; } return *this; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

COMPILER virtual ~Derived() { std::cout << "Derived class dtor"; } static Derived Factory() { return Derived(); } };

static void DerivedFactoryExecution() { Derived::Factory(); }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

COMPILER virtual ~Derived() { std::cout << "Derived class dtor"; } static Derived Factory() { return Derived(); } };

static void DerivedFactoryExecution() { Derived::Factory(); }

Base class ctor - Derived class ctor Base class move ctor - Derived class move ctor Derived class dtor - Base class dtor Derived class dtor - Base class dtor

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

Implicit move constructor conditions

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

Implicit move constructor conditions

movible base class

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

Implicit move constructor conditions

movible base class&& movible inner classes

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

Implicit move constructor conditions

movible base class&& movible inner classes

&& copy constructor not declared

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

Implicit move constructor conditions

movible base class&& movible inner classes

&& copy constructor not declared&& destructor not declared

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

Implicit move operator conditions

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

Implicit move operator conditions

movible base class

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

Implicit move operator conditions

movible base class&& movible inner classes

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

Implicit move operator conditions

movible base class&& movible inner classes

&& copy operator not declared

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

Implicit move operator conditions

movible base class&& movible inner classes

&& copy operator not declared&& destructor not declared

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

How to…implement a new data structure

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

:RBTree

THEORY

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

:RBTree :RBTree

nullptr

THEORY

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

:RBTree :RBTree

nullptr

THEORY

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

:RBTree :RBTree

nullptr

THEORY

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

:RBTree :RBTree

THEORY

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

:RBTree :RBTree

THEORY

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

:RBTree

THEORY

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

:RBTree :RBTree

nullptr

THEORY

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

:RBTree :RBTree

nullptr

THEORY

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

:RBTree:RBTree

nullptr

4. std::move

THEORY

std::move performs an unconditional cast to an rvalue

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

std::move performs an unconditional cast to an rvalue

It doesn’t move anything

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

std::cout << Classifier::WhatIs(std::move(3)) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

std::cout << Classifier::WhatIs(std::move(3)) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; std::cout << Classifier::WhatIs(std::move(ii)) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; std::cout << Classifier::WhatIs(std::move(ii)) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; int &&iiRefRef = ii; std::cout << Classifier::WhatIs(iiRefRef) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; int &&iiRefRef = ii; std::cout << Classifier::WhatIs(iiRefRef) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; int &&iiRefRef = std::move(ii); std::cout << Classifier::WhatIs(iiRefRef) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; int &&iiRefRef = std::move(ii); std::cout << Classifier::WhatIs(iiRefRef) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; int &&iiRefRef = std::move(ii); std::cout << Classifier::WhatIs(std::move(iiRefRef)) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

QUIZ

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

What is the output message?

class Classifier { public: static std::string WhatIs(int &value) { return "lvalue ref”; }

static std::string WhatIs(int &&value) { return "rvalue ref”; } };

int ii = 0; int &&iiRefRef = std::move(ii); std::cout << Classifier::WhatIs(std::move(iiRefRef)) << std::endl;

A. lvalue ref B. rvalue ref

C. Compilation error D. This sentence is false

5. std::forward

THEORY

template <typename T>void foo(T &param);

template <typename T>void foo(T &&param);

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

template <typename T>void foo(T &param);

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

template <typename T>void foo(T &param);

T is int —> foo(int &param)

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

template <typename T>void foo(T &param);

T is int —> foo(int &param)T is int & —> foo(int & &param)

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

template <typename T>void foo(T &param);

T is int —> foo(int &param)T is int & —> foo(int & &param)

T is int && —> foo(int && &param)

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

template <typename T>void foo(T &&param);

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

template <typename T>void foo(T &&param);

T is int —> foo(int &&param)

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

template <typename T>void foo(T &&param);

T is int —> foo(int &&param)T is int & —> foo(int & &&param)

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

template <typename T>void foo(T &&param);

T is int —> foo(int &&param)T is int & —> foo(int & &&param)

T is int && —> foo(int && &&param)

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

Reference collapsing

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

Reference collapsing

T & & —> T &T & && —> T &T && & —> T &

T && && —> T &&

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

template <typename T>void foo(T &&param);

type deduction:T && can be a lvalue ref. or a rvalue ref.

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

template <typename T>void foo(T &&param);

type deduction:T && can be a lvalue ref. or a rvalue ref.

forward references akauniversal references

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Classifier { public: template <typename T> static std::string WhatIs(T &lvalueRef) { return "Classifier: lvalue ref"; }

template <typename T> static std::string WhatIs(T &&rvalueRef) { return "Classifier: rvalue ref"; } };

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Classifier { public: template <typename T> static std::string WhatIs(T &lvalueRef) { return "Classifier: lvalue ref"; }

template <typename T> static std::string WhatIs(T &&rvalueRef) { return "Classifier: rvalue ref"; } };

int ii = 0; std::cout << Classifier::WhatIs(ii) << std::endl; std::cout << Classifier::WhatIs(5) << std::endl; int &iiRef = ii; std::cout << Classifier::WhatIs(iiRef) << std::endl; std::cout << Classifier::WhatIs(std::move(iiRef)) << std::endl;

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Classifier { public: template <typename T> static std::string WhatIs(T &lvalueRef) { return "Classifier: lvalue ref"; }

template <typename T> static std::string WhatIs(T &&rvalueRef) { return "Classifier: rvalue ref"; } };

int ii = 0; std::cout << Classifier::WhatIs(ii) << std::endl; std::cout << Classifier::WhatIs(5) << std::endl; int &iiRef = ii; std::cout << Classifier::WhatIs(iiRef) << std::endl; std::cout << Classifier::WhatIs(std::move(iiRef)) << std::endl;

Classifier: lvalue ref Classifier: rvalue ref Classifier: lvalue ref Classifier: rvalue ref

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Classifier { public: template <typename T> static std::string WhatIs(T &lvalueRef) { return "Classifier: lvalue ref"; }

template <typename T> static std::string WhatIs(T &&rvalueRef) { return "Classifier: rvalue ref"; } };

class StdForward { public: template <typename T> static std::string WhatIs(T &&param) { std::stringstream ss; ss << "StdForward::WhatIs(param) -> "; ss << Classifier::WhatIs(param); return ss.str(); } };

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Classifier { public: template <typename T> static std::string WhatIs(T &lvalueRef) { return "Classifier: lvalue ref"; }

template <typename T> static std::string WhatIs(T &&rvalueRef) { return "Classifier: rvalue ref"; } };

class StdForward { public: template <typename T> static std::string WhatIs(T &&param) { std::stringstream ss; ss << "StdForward::WhatIs(param) -> "; ss << Classifier::WhatIs(param); return ss.str(); } };

int ii = 0; std::cout << StdForward::WhatIs(ii) << std::endl; std::cout << StdForward::WhatIs(5) << std::endl; int &iiRef = ii; std::cout << StdForward::WhatIs(iiRef) << std::endl; std::cout << StdForward::WhatIs(std::move(iiRef)) << std::endl;

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Classifier { public: template <typename T> static std::string WhatIs(T &lvalueRef) { return "Classifier: lvalue ref"; }

template <typename T> static std::string WhatIs(T &&rvalueRef) { return "Classifier: rvalue ref"; } };

class StdForward { public: template <typename T> static std::string WhatIs(T &&param) { std::stringstream ss; ss << "StdForward::WhatIs(param) -> "; ss << Classifier::WhatIs(param); return ss.str(); } };

int ii = 0; std::cout << StdForward::WhatIs(ii) << std::endl; std::cout << StdForward::WhatIs(5) << std::endl; int &iiRef = ii; std::cout << StdForward::WhatIs(iiRef) << std::endl; std::cout << StdForward::WhatIs(std::move(iiRef)) << std::endl;

StdForward::WhatIs(param) -> Classifier: lvalue ref StdForward::WhatIs(param) -> Classifier: lvalue ref StdForward::WhatIs(param) -> Classifier: lvalue ref StdForward::WhatIs(param) -> Classifier: lvalue ref

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Classifier { public: template <typename T> static std::string WhatIs(T &lvalueRef) { return "Classifier: lvalue ref"; }

template <typename T> static std::string WhatIs(T &&rvalueRef) { return "Classifier: rvalue ref"; } };

class StdForward { public: template <typename T> static std::string WhatIs(T &&param) { std::stringstream ss; ss << "StdForward::WhatIs(param) -> "; ss << Classifier::WhatIs(param); return ss.str(); } };

int ii = 0; std::cout << StdForward::WhatIs(ii) << std::endl; std::cout << StdForward::WhatIs(5) << std::endl; int &iiRef = ii; std::cout << StdForward::WhatIs(iiRef) << std::endl; std::cout << StdForward::WhatIs(std::move(iiRef)) << std::endl;

StdForward::WhatIs(param) -> Classifier: lvalue ref StdForward::WhatIs(param) -> Classifier: lvalue ref StdForward::WhatIs(param) -> Classifier: lvalue ref StdForward::WhatIs(param) -> Classifier: lvalue ref

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Classifier { public: template <typename T> static std::string WhatIs(T &lvalueRef) { return "Classifier: lvalue ref"; }

template <typename T> static std::string WhatIs(T &&rvalueRef) { return "Classifier: rvalue ref"; } };

class StdForward { public: template <typename T> static std::string WhatIs(T &&param) { std::stringstream ss; ss << "StdForward::WhatIs(param) -> "; ss << Classifier::WhatIs(std::move(param)); return ss.str(); } };

int ii = 0; std::cout << StdForward::WhatIs(ii) << std::endl; std::cout << StdForward::WhatIs(5) << std::endl; int &iiRef = ii; std::cout << StdForward::WhatIs(iiRef) << std::endl; std::cout << StdForward::WhatIs(std::move(iiRef)) << std::endl;

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Classifier { public: template <typename T> static std::string WhatIs(T &lvalueRef) { return "Classifier: lvalue ref"; }

template <typename T> static std::string WhatIs(T &&rvalueRef) { return "Classifier: rvalue ref"; } };

class StdForward { public: template <typename T> static std::string WhatIs(T &&param) { std::stringstream ss; ss << "StdForward::WhatIs(param) -> "; ss << Classifier::WhatIs(std::move(param)); return ss.str(); } };

int ii = 0; std::cout << StdForward::WhatIs(ii) << std::endl; std::cout << StdForward::WhatIs(5) << std::endl; int &iiRef = ii; std::cout << StdForward::WhatIs(iiRef) << std::endl; std::cout << StdForward::WhatIs(std::move(iiRef)) << std::endl;

StdForward::WhatIs(param) -> Classifier: rvalue ref StdForward::WhatIs(param) -> Classifier: rvalue ref StdForward::WhatIs(param) -> Classifier: rvalue ref StdForward::WhatIs(param) -> Classifier: rvalue ref

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Classifier { public: template <typename T> static std::string WhatIs(T &lvalueRef) { return "Classifier: lvalue ref"; }

template <typename T> static std::string WhatIs(T &&rvalueRef) { return "Classifier: rvalue ref"; } };

class StdForward { public: template <typename T> static std::string WhatIs(T &&param) { std::stringstream ss; ss << "StdForward::WhatIs(param) -> "; ss << Classifier::WhatIs(std::move(param)); return ss.str(); } };

int ii = 0; std::cout << StdForward::WhatIs(ii) << std::endl; std::cout << StdForward::WhatIs(5) << std::endl; int &iiRef = ii; std::cout << StdForward::WhatIs(iiRef) << std::endl; std::cout << StdForward::WhatIs(std::move(iiRef)) << std::endl;

StdForward::WhatIs(param) -> Classifier: rvalue ref StdForward::WhatIs(param) -> Classifier: rvalue ref StdForward::WhatIs(param) -> Classifier: rvalue ref StdForward::WhatIs(param) -> Classifier: rvalue ref

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Classifier { public: template <typename T> static std::string WhatIs(T &lvalueRef) { return "Classifier: lvalue ref"; }

template <typename T> static std::string WhatIs(T &&rvalueRef) { return "Classifier: rvalue ref"; } };

class StdForward { public: template <typename T> static std::string WhatIs(T &&param) { std::stringstream ss; ss << "StdForward::WhatIs(param) -> "; ss << Classifier::WhatIs(std::forward<T>(param)); return ss.str(); } };

int ii = 0; std::cout << StdForward::WhatIs(ii) << std::endl; std::cout << StdForward::WhatIs(5) << std::endl; int &iiRef = ii; std::cout << StdForward::WhatIs(iiRef) << std::endl; std::cout << StdForward::WhatIs(std::move(iiRef)) << std::endl;

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERclass Classifier { public: template <typename T> static std::string WhatIs(T &lvalueRef) { return "Classifier: lvalue ref"; }

template <typename T> static std::string WhatIs(T &&rvalueRef) { return "Classifier: rvalue ref"; } };

class StdForward { public: template <typename T> static std::string WhatIs(T &&param) { std::stringstream ss; ss << "StdForward::WhatIs(param) -> "; ss << Classifier::WhatIs(std::forward<T>(param)); return ss.str(); } };

int ii = 0; std::cout << StdForward::WhatIs(ii) << std::endl; std::cout << StdForward::WhatIs(5) << std::endl; int &iiRef = ii; std::cout << StdForward::WhatIs(iiRef) << std::endl; std::cout << StdForward::WhatIs(std::move(iiRef)) << std::endl;

StdForward::WhatIs(param) -> Classifier: lvalue ref StdForward::WhatIs(param) -> Classifier: rvalue ref StdForward::WhatIs(param) -> Classifier: lvalue ref StdForward::WhatIs(param) -> Classifier: rvalue ref

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

std::forward cast its argument to an rvalue only if that argument is bound to a

rvalue

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

THEORY

std::forward cast its argument to an rvalue only if that argument is bound to a

rvalue

It doesn’t forward anything

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERtemplate <typename T> static void DoSomething(T &&param) { std::cout << "DoSomething(" << StdForward::WhatIs(std::forward<T>(param)) << ')'; }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERtemplate <typename T> static void DoSomething(T &&param) { std::cout << "DoSomething(" << StdForward::WhatIs(std::forward<T>(param)) << ')'; }

template <class T, class... Args> static void DoSomething(T &&first, Args &&... args) { DoSomething(std::forward<T>(first)); std::cout << std::endl; DoSomething(std::forward<Args>(args)...); }

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERtemplate <typename T> static void DoSomething(T &&param) { std::cout << "DoSomething(" << StdForward::WhatIs(std::forward<T>(param)) << ')'; }

template <class T, class... Args> static void DoSomething(T &&first, Args &&... args) { DoSomething(std::forward<T>(first)); std::cout << std::endl; DoSomething(std::forward<Args>(args)...); }

int value = 0; std::string str = "Hello!"; std::string otherStr = "Bye"; DoSomething(value, 5, str, std::move(otherStr));

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

1 2 3 4 5 6 7 8 9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

COMPILERtemplate <typename T> static void DoSomething(T &&param) { std::cout << "DoSomething(" << StdForward::WhatIs(std::forward<T>(param)) << ')'; }

template <class T, class... Args> static void DoSomething(T &&first, Args &&... args) { DoSomething(std::forward<T>(first)); std::cout << std::endl; DoSomething(std::forward<Args>(args)...); }

int value = 0; std::string str = "Hello!"; std::string otherStr = "Bye"; DoSomething(value, 5, str, std::move(otherStr));

DoSomething(StdForward::WhatIs(param) -> Classifier: lvalue ref) DoSomething(StdForward::WhatIs(param) -> Classifier: rvalue ref) DoSomething(StdForward::WhatIs(param) -> Classifier: lvalue ref) DoSomething(StdForward::WhatIs(param) -> Classifier: rvalue ref)

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

6. The End

RECAP

use non modifiable classes

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

RECAP

use non modifiable classes

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

RECAP

use non copyable classes

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

RECAP

use non copyable classes

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

RECAP

use default or delete in constructors and assign operators

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

RECAP

use default or delete in constructors and assign operators

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

RECAP

use std::move with rvalue refs.

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

RECAP

use std::move with rvalue refs.

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

RECAP

use std::forward with fvalue refs.

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

RECAP

use std::forward with fvalue refs.

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

ADVICE

do not use const in move constructor or move operator

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

ADVICE

do not use const in move constructor or move operator

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

ADVICE

moves are not always more efficientthan copies

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

ADVICE

moves are not always more efficientthan copies

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

ADVICE

caution with moves in multithreaded environments

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End

ADVICE

caution with moves in multithreaded environments

NonCopyable

lvalue & rvalue refs.

move ctor. & optor.

std::move

std::forward

The End