move semantics c++11/14 fileindex • non copyable classes • lvalue and rvalue references • move...
TRANSCRIPT
Index• Non copyable classes
• lvalue and rvalue references
• move constructor and move operator
• 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; }
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
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 = ⅈ 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 = ⅈ 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 = ⅈ 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 = ⅈ 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
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 :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 :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
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
THEORY
template <typename T>void foo(T ¶m);
template <typename T>void foo(T &¶m);
NonCopyable
lvalue & rvalue refs.
move ctor. & optor.
std::move
std::forward
The End
THEORY
template <typename T>void foo(T ¶m);
NonCopyable
lvalue & rvalue refs.
move ctor. & optor.
std::move
std::forward
The End
THEORY
template <typename T>void foo(T ¶m);
T is int —> foo(int ¶m)
NonCopyable
lvalue & rvalue refs.
move ctor. & optor.
std::move
std::forward
The End
THEORY
template <typename T>void foo(T ¶m);
T is int —> foo(int ¶m)T is int & —> foo(int & ¶m)
NonCopyable
lvalue & rvalue refs.
move ctor. & optor.
std::move
std::forward
The End
THEORY
template <typename T>void foo(T ¶m);
T is int —> foo(int ¶m)T is int & —> foo(int & ¶m)
T is int && —> foo(int && ¶m)
NonCopyable
lvalue & rvalue refs.
move ctor. & optor.
std::move
std::forward
The End
THEORY
template <typename T>void foo(T &¶m);
NonCopyable
lvalue & rvalue refs.
move ctor. & optor.
std::move
std::forward
The End
THEORY
template <typename T>void foo(T &¶m);
T is int —> foo(int &¶m)
NonCopyable
lvalue & rvalue refs.
move ctor. & optor.
std::move
std::forward
The End
THEORY
template <typename T>void foo(T &¶m);
T is int —> foo(int &¶m)T is int & —> foo(int & &¶m)
NonCopyable
lvalue & rvalue refs.
move ctor. & optor.
std::move
std::forward
The End
THEORY
template <typename T>void foo(T &¶m);
T is int —> foo(int &¶m)T is int & —> foo(int & &¶m)
T is int && —> foo(int && &¶m)
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 &¶m);
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 &¶m);
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 &¶m) { 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 &¶m) { 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 &¶m) { 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 &¶m) { 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 &¶m) { 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 &¶m) { 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 &¶m) { 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 &¶m) { 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 &¶m) { 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 &¶m) { 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 &¶m) { 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 &¶m) { 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 &¶m) { 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
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