Rvalue References,
Move Semantics,
Perfect Forwarding
Francesco Casalegno
In this presentation...
1. Understanding fearsome code!
template <typename T, typename... Arg>
std::shared_ptr<T> factory_make(Arg&&... arg) {
return std::shared_ptr<T>(new T(std::forward<Arg>(arg)... ));
}
2. Universal References are not Rvalue References!
3. How forgetting a “noexcept” can wreck your performance!
template<class T>
void foo(std::vector<T>&& v); // this is an rvalue reference…
template<class T>
void foo(T&& v); // this is NOT an rvalue reference!
Vector(Vector&& other); // horrible things may now happen!
2
Lvalues VS Rvalues
According to the Standard:
● lvalue: expression referring to a memory location, allowing to take the address using operator &
● rvalue: everything else, i.e. address may not be taken and cannot use them as l.h.s. in assignment
● (rvalues are further divided into prvalues and xvalues: not discussed today)
Your turn! Lvalues or rvalues?
X foo() { X x(5, "Joe"); return x; }
int a(7);
int b = ++a; // what is ++a ?
int c = b--; // what is b-- ?
X x = X(6, "Jane"); // what is X(6, "Jane") ?
int* v = new int[10];
int d = v[7]; // what is v[7] ?
int e = a+b; // what is a+b ?
X f = foo(); // what is foo() ?
struct bar {
private:
int val_;
public:
…
bar& operator=(bar const& other) {
val_ = other.val_;
return *this; // what is this ?
}
};
3
Lvalue References
Pre C++11 we only had lvalue references
int x =5; int& a = x;
● act as an alias of valid existing object
a = 5; // now also x contains 5!
● used to implement pass-by-reference semantics (avoiding pointers!)
void double_vals(std::vector<int>& v) {...}
● can only bind to lvalues…
std::vector<int> v(10);
double_vals(v); // ok!
double_vals(std::vector<int>(10)); // no!
● … unless they are const lvalue references!
void print_vals(std::vector<int> const& v)
print_vals(std::vector<int>(10)); // ok !
Your turn!
Why would it not make sense for a non-const lvalue reference to bind an rvalue? 4
Rvalue References
In C++11 we also have rvalue references: int&& a = 5;
● can only bind to rvalues: they extend the life of temporary objects
int x = 5;
int& a = 3; // no!
int const& b = 3; // ok!
int&& c = 3; // ok!
int&& d = x; // no!
● unlike const lvalue reference, rvalue reference allow to modify the object!
void print_vals(std::vector<int> const& v); // may take either lvalues or rvalue, but not modify it!
void print_vals(std::vector<int> && v); // may take rvalue, and also modify it!
● in case of function overloading, preferred over const lvalue reference
bool is_temporary_int(int const&) {return false;}
bool is_temporary_int(const&&) {return true;}
Your turn!
What’s the output?
5
int x = 1;
is_temporary_int(3);
is_temporary_int(x);
is_temporary_int(x++);
is_temporary_int(++x);
Move Semantics
Let us consider a class holding some kind of resource:
Pre C++11 we had the Rule of Three: (copy assignment, copy c-tor, d-tor)
● But assignment / copy c-tor can be very expensive for rvalues!
Vec foo() { Vec v(1e9); return v; }
Vec w;
w = foo()
● Potentially, we have:
a. c-tor called for w
b. c-tor called for v
c. copy c-tor called for v into temporary (huge!)
d. copy assignment called for temporary into w (huge!)
● If the compiler is smart, c. may be avoided, but no chance for d. ...
○ However, the temporary returned by foo() is not needed any more...
○ Idea: pilfer the temporary’s data and put it into w without copying values: Move Semantics
○ Rule of Five (move assignment, move c-tor) to pilfer instead of copying data for rvalues
6
class Vec {
int* data_;
size_t size_; …
};
Copy C-tor VS Move C-tor
Copy C-tor
// Copy c-tor:
// 1. allocate space
// 2. copy values from other
Vec(Vec const& other) :
size_(other.size_),
data_(new int[size_])
{
for (int i=0; i<size_; ++i)
data_[i] = other.data_[i];
}
7
Move C-tor
// Move c-tor:
// 1. pilfer data
// 2. set other to nullptr for safe destruction
Vec(Vec&& other) :
size_(other.size_),
data_(other.data_)
{
other.data_ = nullptr;
other.size_ = 0;
}
Copy assignment VS Move assignment: similarly, but check for self-assignment!
Your turn! What happens if we do not set to nullptr after moving?
Forcing move semantics with std::move
Sometimes we have an lvalues, but we want to call the rvalue copy c-tor / assignment.
std::move (#include <utility>) will do the trick by casting to an rvalue reference!
● Ex 1. std::swap
template <class T> void swap (T& a, T& b) {
T c(std::move(a)); a=std::move(b); b=std::move(c);
}
● Ex2. steal ownership for non-assignable and non-copyable (but movable!) objects
std::unique_ptr<double> p1(new double);
std::unique_ptr<double> p2(new double);
p2 = p1; // no!
p2 = std::move(p1); // ok: call d-tor for p1, then pilfer data!
● Ex3. force move semantics by virtue of has-a-name rule: a named rvalue reference is an lvalue
class NamedWrap {
char* nm_;
Vec v_;
NamedWrap(NamedWrap&& other) : // move c-tor
nm_(other.nm_),
v_(std::move(other.v_)) // other is named rvalue reference, without std::move will call copy c-tor!!
{
other.nm_ = nullptr;
}
};
8
When copying is useless: Copy Elision
● The Standard allows the compiler to elide copy or move c-tor–regardless of side effects!–in the following cases:
// 1 . return value optimization
X foo() { X a; return a;}
X p = foo();
// 2. temporary object passed by value
void bar(X x); bar(X(1,"Bob"));
// 3. exception caught by value
void qux() { X c; throw c; }
try{ qux(); }
catch(X except) {some_fun();}
● But then, why do we still need move c-tor?
○ multiple return points and conditional initialization prevent copy/move elision
○ copy/move elision may have desirable side effects: -fno-elide-constructors
○ copy/move elision is only allowed, but not prescribed, by the Standard
○ also, notice that copy/move assignment may not be elided
Your turn! Even using the world's smartest compiler, if we do not implement move c-tor and move
assignment for class X, calling std::sort() on an array of X may take ages. Why? 9
Universal References
● The Standard forbids the construction of a reference to a reference. However, the following is allowed:
template <class T> void foo(T a, T& b);
int x, y;
foo<int&>(x,y); // call to foo(int& , int& &) ??
To solve this, the Standard prescribes collapsing rules:
X & & --> X &
X && & --> X &
X & && --> X &
X && && --> X &&
● Universal reference: && is right-neutral, so it can be used in templates as T&& to match any reference!
template <class T> void foo(T&& a);
int x = 7;
foo(x); // call foo(int& a)
foo(5); // call foo(int&& a)
Your turn!
Do the collapsing rules look similar to a logical operation?
10
Universal reference: && is right-neutral, so it can be
used in templates as T&& with automatic deduction
to match any reference!
Perfect Forwarding with std::forward
● Perfect Forwarding problem: pass an argument arg by lvalue/rvalue reference to foo(), and inside the body of
foo() call bar() with same arg and preserving its nature of lvalue/rvalue reference.
○ Why a problem? arg has-a-name, therefore is always an lvalue for bar!
● Solution: std::forward(arg) (#include <utility>) returns an rvalue reference to arg if arg is not an lvalue reference, and
otherwise it returns arg without modifying its type.
● Classical application: factory pattern
11
bool is_temp(int const&) {return false;}
bool is_temp(int &&) {return true;}
template <class T>
void print_is_temp(T&& arg) {
std::cout << is_temp(arg) << std::endl; // attention! arg has-a-name...
}
print_is_temp(5); // print false!
...
std::cout << is_temp(std::forward(arg)) << std::endl;
}
print_is_temp(5); // print true!
template <typename T, typename... Arg>
std::shared_ptr<T> factory_make(Arg&&... arg) { // 1. Universal Reference
return std::shared_ptr<T>(new T(std::forward<Arg>(arg)... )); // 2. Forward Argument
}
The noexcept keyword
● The C++11 keyword noexcept is used in the signature of a function to guarantee it will not throw any exception. Unlike
throw() it is checked at compile time and allows optimization that would otherwise be impossible.
● Rule: always make sure that your move c-tor and move assignment are exception safe, and mark these functions as
noexcept!
● If we forget the noexcept for class X, std::vector<X>::resize(int n) will call the copy c-tor and wreck performances!
Your turn!
Why should resize() call the copy c-tor even if the old (smaller size) array is not needed any more after resizing?
12
Take Home Message
1. Implement move c-tor and move assignment following the Rule of Five: usually this is the case for classes with a
X* data_ member!
2. Use std::move to cast to rvalue reference: force Move Semantics (Has-A-Name rule) or steal ownership (if
non-copyable/non-assignable e.g. unique_ptr)
3. Use std::forward to implement Perfect Forwarding: preserve nature of rvalue/lvalue reference when forwarding a
template argument (with Universal References)
4. Do not forget to mark as noexcept both move c-tor and move assignment
13

More Related Content

PDF
Go Concurrency
PDF
Smart Pointers in C++
PPT
Coding Standards & Best Practices for iOS/C#
PDF
An introduction to Rust: the modern programming language to develop safe and ...
PPTX
php and sapi and zendengine2 and...
PPTX
Smart pointers
PDF
Exception handling
PPTX
Coding standards for java
Go Concurrency
Smart Pointers in C++
Coding Standards & Best Practices for iOS/C#
An introduction to Rust: the modern programming language to develop safe and ...
php and sapi and zendengine2 and...
Smart pointers
Exception handling
Coding standards for java

What's hot (20)

PPTX
How Functions Work
PDF
Hot C++: Rvalue References And Move Semantics
PDF
Clean code
PDF
Insecure coding in C (and C++)
PDF
The Rust Programming Language: an Overview
PDF
POINTERS IN C MRS.SOWMYA JYOTHI.pdf
PDF
Modern c++ (C++ 11/14)
PDF
Pointers
PPTX
Rust vs C++
PPT
Functions in C++
PPTX
Rust programming-language
PDF
STRUCTURE AND UNION IN C MRS.SOWMYA JYOTHI.pdf
PPTX
If else statement in c++
PPT
Generics in java
PPTX
Coding standards and guidelines
PDF
Interpreter, Compiler, JIT from scratch
PPTX
Exceptions in Java
PPTX
Exception handling
PPTX
Dynamic memory allocation
PPTX
C# lecture 1: Introduction to Dot Net Framework
How Functions Work
Hot C++: Rvalue References And Move Semantics
Clean code
Insecure coding in C (and C++)
The Rust Programming Language: an Overview
POINTERS IN C MRS.SOWMYA JYOTHI.pdf
Modern c++ (C++ 11/14)
Pointers
Rust vs C++
Functions in C++
Rust programming-language
STRUCTURE AND UNION IN C MRS.SOWMYA JYOTHI.pdf
If else statement in c++
Generics in java
Coding standards and guidelines
Interpreter, Compiler, JIT from scratch
Exceptions in Java
Exception handling
Dynamic memory allocation
C# lecture 1: Introduction to Dot Net Framework
Ad

Similar to C++11: Rvalue References, Move Semantics, Perfect Forwarding (20)

PDF
C++ references
PDF
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
PPTX
C++11 - A Change in Style - v2.0
PDF
Cpp17 and Beyond
PDF
C++ boot camp part 1/2
PDF
C++ Boot Camp Part 1
PDF
Functions And Header Files In C++ | Bjarne stroustrup
PDF
[OLD VERSION, SEE DESCRIPTION FOR THE NEWER VERSION LINK] Hot С++: Universal ...
PDF
Hot С++: Universal References And Perfect Forwarding
PPTX
The Future of C++
PPTX
C Programming Homework Help
PDF
C++aptitude questions and answers
PPTX
CPP Homework Help
PDF
[C++] The Curiously Recurring Template Pattern: Static Polymorphsim and Expre...
PPTX
What’s new in .NET
PPTX
Object oriented programming system with C++
PPTX
Namespaces
PDF
Milot Shala - C++ (OSCAL2014)
PPTX
Presentation 5th
C++ references
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++11 - A Change in Style - v2.0
Cpp17 and Beyond
C++ boot camp part 1/2
C++ Boot Camp Part 1
Functions And Header Files In C++ | Bjarne stroustrup
[OLD VERSION, SEE DESCRIPTION FOR THE NEWER VERSION LINK] Hot С++: Universal ...
Hot С++: Universal References And Perfect Forwarding
The Future of C++
C Programming Homework Help
C++aptitude questions and answers
CPP Homework Help
[C++] The Curiously Recurring Template Pattern: Static Polymorphsim and Expre...
What’s new in .NET
Object oriented programming system with C++
Namespaces
Milot Shala - C++ (OSCAL2014)
Presentation 5th
Ad

More from Francesco Casalegno (6)

PDF
DVC - Git-like Data Version Control for Machine Learning projects
PDF
Ordinal Regression and Machine Learning: Applications, Methods, Metrics
PDF
Recommender Systems
PDF
Markov Chain Monte Carlo Methods
PDF
Hyperparameter Optimization for Machine Learning
PDF
Confidence Intervals––Exact Intervals, Jackknife, and Bootstrap
DVC - Git-like Data Version Control for Machine Learning projects
Ordinal Regression and Machine Learning: Applications, Methods, Metrics
Recommender Systems
Markov Chain Monte Carlo Methods
Hyperparameter Optimization for Machine Learning
Confidence Intervals––Exact Intervals, Jackknife, and Bootstrap

Recently uploaded (20)

PDF
CXOs-Are-you-still-doing-manual-DevOps-in-the-age-of-AI.pdf
PDF
IT-ITes Industry bjjbnkmkhkhknbmhkhmjhjkhj
PDF
The-Future-of-Automotive-Quality-is-Here-AI-Driven-Engineering.pdf
PDF
A hybrid framework for wild animal classification using fine-tuned DenseNet12...
PPTX
AI-driven Assurance Across Your End-to-end Network With ThousandEyes
PDF
MENA-ECEONOMIC-CONTEXT-VC MENA-ECEONOMIC
PDF
Introduction to MCP and A2A Protocols: Enabling Agent Communication
PDF
Aug23rd - Mulesoft Community Workshop - Hyd, India.pdf
PPTX
Module 1 Introduction to Web Programming .pptx
PDF
Data Virtualization in Action: Scaling APIs and Apps with FME
PDF
Planning-an-Audit-A-How-To-Guide-Checklist-WP.pdf
PDF
Advancing precision in air quality forecasting through machine learning integ...
PDF
Transform-Quality-Engineering-with-AI-A-60-Day-Blueprint-for-Digital-Success.pdf
PDF
zbrain.ai-Scope Key Metrics Configuration and Best Practices.pdf
PDF
Ensemble model-based arrhythmia classification with local interpretable model...
PDF
Transform-Your-Supply-Chain-with-AI-Driven-Quality-Engineering.pdf
PDF
Dell Pro Micro: Speed customer interactions, patient processing, and learning...
PDF
Transform-Your-Streaming-Platform-with-AI-Driven-Quality-Engineering.pdf
PPTX
Presentation - Principles of Instructional Design.pptx
PDF
LMS bot: enhanced learning management systems for improved student learning e...
CXOs-Are-you-still-doing-manual-DevOps-in-the-age-of-AI.pdf
IT-ITes Industry bjjbnkmkhkhknbmhkhmjhjkhj
The-Future-of-Automotive-Quality-is-Here-AI-Driven-Engineering.pdf
A hybrid framework for wild animal classification using fine-tuned DenseNet12...
AI-driven Assurance Across Your End-to-end Network With ThousandEyes
MENA-ECEONOMIC-CONTEXT-VC MENA-ECEONOMIC
Introduction to MCP and A2A Protocols: Enabling Agent Communication
Aug23rd - Mulesoft Community Workshop - Hyd, India.pdf
Module 1 Introduction to Web Programming .pptx
Data Virtualization in Action: Scaling APIs and Apps with FME
Planning-an-Audit-A-How-To-Guide-Checklist-WP.pdf
Advancing precision in air quality forecasting through machine learning integ...
Transform-Quality-Engineering-with-AI-A-60-Day-Blueprint-for-Digital-Success.pdf
zbrain.ai-Scope Key Metrics Configuration and Best Practices.pdf
Ensemble model-based arrhythmia classification with local interpretable model...
Transform-Your-Supply-Chain-with-AI-Driven-Quality-Engineering.pdf
Dell Pro Micro: Speed customer interactions, patient processing, and learning...
Transform-Your-Streaming-Platform-with-AI-Driven-Quality-Engineering.pdf
Presentation - Principles of Instructional Design.pptx
LMS bot: enhanced learning management systems for improved student learning e...

C++11: Rvalue References, Move Semantics, Perfect Forwarding

  • 1. Rvalue References, Move Semantics, Perfect Forwarding Francesco Casalegno
  • 2. In this presentation... 1. Understanding fearsome code! template <typename T, typename... Arg> std::shared_ptr<T> factory_make(Arg&&... arg) { return std::shared_ptr<T>(new T(std::forward<Arg>(arg)... )); } 2. Universal References are not Rvalue References! 3. How forgetting a “noexcept” can wreck your performance! template<class T> void foo(std::vector<T>&& v); // this is an rvalue reference… template<class T> void foo(T&& v); // this is NOT an rvalue reference! Vector(Vector&& other); // horrible things may now happen! 2
  • 3. Lvalues VS Rvalues According to the Standard: ● lvalue: expression referring to a memory location, allowing to take the address using operator & ● rvalue: everything else, i.e. address may not be taken and cannot use them as l.h.s. in assignment ● (rvalues are further divided into prvalues and xvalues: not discussed today) Your turn! Lvalues or rvalues? X foo() { X x(5, "Joe"); return x; } int a(7); int b = ++a; // what is ++a ? int c = b--; // what is b-- ? X x = X(6, "Jane"); // what is X(6, "Jane") ? int* v = new int[10]; int d = v[7]; // what is v[7] ? int e = a+b; // what is a+b ? X f = foo(); // what is foo() ? struct bar { private: int val_; public: … bar& operator=(bar const& other) { val_ = other.val_; return *this; // what is this ? } }; 3
  • 4. Lvalue References Pre C++11 we only had lvalue references int x =5; int& a = x; ● act as an alias of valid existing object a = 5; // now also x contains 5! ● used to implement pass-by-reference semantics (avoiding pointers!) void double_vals(std::vector<int>& v) {...} ● can only bind to lvalues… std::vector<int> v(10); double_vals(v); // ok! double_vals(std::vector<int>(10)); // no! ● … unless they are const lvalue references! void print_vals(std::vector<int> const& v) print_vals(std::vector<int>(10)); // ok ! Your turn! Why would it not make sense for a non-const lvalue reference to bind an rvalue? 4
  • 5. Rvalue References In C++11 we also have rvalue references: int&& a = 5; ● can only bind to rvalues: they extend the life of temporary objects int x = 5; int& a = 3; // no! int const& b = 3; // ok! int&& c = 3; // ok! int&& d = x; // no! ● unlike const lvalue reference, rvalue reference allow to modify the object! void print_vals(std::vector<int> const& v); // may take either lvalues or rvalue, but not modify it! void print_vals(std::vector<int> && v); // may take rvalue, and also modify it! ● in case of function overloading, preferred over const lvalue reference bool is_temporary_int(int const&) {return false;} bool is_temporary_int(const&&) {return true;} Your turn! What’s the output? 5 int x = 1; is_temporary_int(3); is_temporary_int(x); is_temporary_int(x++); is_temporary_int(++x);
  • 6. Move Semantics Let us consider a class holding some kind of resource: Pre C++11 we had the Rule of Three: (copy assignment, copy c-tor, d-tor) ● But assignment / copy c-tor can be very expensive for rvalues! Vec foo() { Vec v(1e9); return v; } Vec w; w = foo() ● Potentially, we have: a. c-tor called for w b. c-tor called for v c. copy c-tor called for v into temporary (huge!) d. copy assignment called for temporary into w (huge!) ● If the compiler is smart, c. may be avoided, but no chance for d. ... ○ However, the temporary returned by foo() is not needed any more... ○ Idea: pilfer the temporary’s data and put it into w without copying values: Move Semantics ○ Rule of Five (move assignment, move c-tor) to pilfer instead of copying data for rvalues 6 class Vec { int* data_; size_t size_; … };
  • 7. Copy C-tor VS Move C-tor Copy C-tor // Copy c-tor: // 1. allocate space // 2. copy values from other Vec(Vec const& other) : size_(other.size_), data_(new int[size_]) { for (int i=0; i<size_; ++i) data_[i] = other.data_[i]; } 7 Move C-tor // Move c-tor: // 1. pilfer data // 2. set other to nullptr for safe destruction Vec(Vec&& other) : size_(other.size_), data_(other.data_) { other.data_ = nullptr; other.size_ = 0; } Copy assignment VS Move assignment: similarly, but check for self-assignment! Your turn! What happens if we do not set to nullptr after moving?
  • 8. Forcing move semantics with std::move Sometimes we have an lvalues, but we want to call the rvalue copy c-tor / assignment. std::move (#include <utility>) will do the trick by casting to an rvalue reference! ● Ex 1. std::swap template <class T> void swap (T& a, T& b) { T c(std::move(a)); a=std::move(b); b=std::move(c); } ● Ex2. steal ownership for non-assignable and non-copyable (but movable!) objects std::unique_ptr<double> p1(new double); std::unique_ptr<double> p2(new double); p2 = p1; // no! p2 = std::move(p1); // ok: call d-tor for p1, then pilfer data! ● Ex3. force move semantics by virtue of has-a-name rule: a named rvalue reference is an lvalue class NamedWrap { char* nm_; Vec v_; NamedWrap(NamedWrap&& other) : // move c-tor nm_(other.nm_), v_(std::move(other.v_)) // other is named rvalue reference, without std::move will call copy c-tor!! { other.nm_ = nullptr; } }; 8
  • 9. When copying is useless: Copy Elision ● The Standard allows the compiler to elide copy or move c-tor–regardless of side effects!–in the following cases: // 1 . return value optimization X foo() { X a; return a;} X p = foo(); // 2. temporary object passed by value void bar(X x); bar(X(1,"Bob")); // 3. exception caught by value void qux() { X c; throw c; } try{ qux(); } catch(X except) {some_fun();} ● But then, why do we still need move c-tor? ○ multiple return points and conditional initialization prevent copy/move elision ○ copy/move elision may have desirable side effects: -fno-elide-constructors ○ copy/move elision is only allowed, but not prescribed, by the Standard ○ also, notice that copy/move assignment may not be elided Your turn! Even using the world's smartest compiler, if we do not implement move c-tor and move assignment for class X, calling std::sort() on an array of X may take ages. Why? 9
  • 10. Universal References ● The Standard forbids the construction of a reference to a reference. However, the following is allowed: template <class T> void foo(T a, T& b); int x, y; foo<int&>(x,y); // call to foo(int& , int& &) ?? To solve this, the Standard prescribes collapsing rules: X & & --> X & X && & --> X & X & && --> X & X && && --> X && ● Universal reference: && is right-neutral, so it can be used in templates as T&& to match any reference! template <class T> void foo(T&& a); int x = 7; foo(x); // call foo(int& a) foo(5); // call foo(int&& a) Your turn! Do the collapsing rules look similar to a logical operation? 10 Universal reference: && is right-neutral, so it can be used in templates as T&& with automatic deduction to match any reference!
  • 11. Perfect Forwarding with std::forward ● Perfect Forwarding problem: pass an argument arg by lvalue/rvalue reference to foo(), and inside the body of foo() call bar() with same arg and preserving its nature of lvalue/rvalue reference. ○ Why a problem? arg has-a-name, therefore is always an lvalue for bar! ● Solution: std::forward(arg) (#include <utility>) returns an rvalue reference to arg if arg is not an lvalue reference, and otherwise it returns arg without modifying its type. ● Classical application: factory pattern 11 bool is_temp(int const&) {return false;} bool is_temp(int &&) {return true;} template <class T> void print_is_temp(T&& arg) { std::cout << is_temp(arg) << std::endl; // attention! arg has-a-name... } print_is_temp(5); // print false! ... std::cout << is_temp(std::forward(arg)) << std::endl; } print_is_temp(5); // print true! template <typename T, typename... Arg> std::shared_ptr<T> factory_make(Arg&&... arg) { // 1. Universal Reference return std::shared_ptr<T>(new T(std::forward<Arg>(arg)... )); // 2. Forward Argument }
  • 12. The noexcept keyword ● The C++11 keyword noexcept is used in the signature of a function to guarantee it will not throw any exception. Unlike throw() it is checked at compile time and allows optimization that would otherwise be impossible. ● Rule: always make sure that your move c-tor and move assignment are exception safe, and mark these functions as noexcept! ● If we forget the noexcept for class X, std::vector<X>::resize(int n) will call the copy c-tor and wreck performances! Your turn! Why should resize() call the copy c-tor even if the old (smaller size) array is not needed any more after resizing? 12
  • 13. Take Home Message 1. Implement move c-tor and move assignment following the Rule of Five: usually this is the case for classes with a X* data_ member! 2. Use std::move to cast to rvalue reference: force Move Semantics (Has-A-Name rule) or steal ownership (if non-copyable/non-assignable e.g. unique_ptr) 3. Use std::forward to implement Perfect Forwarding: preserve nature of rvalue/lvalue reference when forwarding a template argument (with Universal References) 4. Do not forget to mark as noexcept both move c-tor and move assignment 13