0% found this document useful (0 votes)
4 views23 pages

C++ Move Semantics Overview

The document discusses C++ move semantics, focusing on the use of std::move() to optimize resource management and avoid unnecessary copies. It provides examples of how to use move semantics in various scenarios, including working with containers like std::vector. The content is presented in the context of a presentation given by Nico Josuttis at CppCon 2021.

Uploaded by

Devanshu
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views23 pages

C++ Move Semantics Overview

The document discusses C++ move semantics, focusing on the use of std::move() to optimize resource management and avoid unnecessary copies. It provides examples of how to use move semantics in various scenarios, including working with containers like std::vector. The content is presented in the context of a presentation given by Nico Josuttis at CppCon 2021.

Uploaded by

Devanshu
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Nico Josuttis C++ Move Semantics

& 
‹E\MRVXWWLVFRP

1LFRODL0-RVXWWLV

‡ ,QGHSHQGHQWFRQVXOWDQW
± &RQWLQXRXVO\OHDUQLQJVLQFH

‡ &
± VLQFH
± ,626WDQGDUG&RPPLWWHHVLQFH

‡ 2WKHU7RSLFV
± 6\VWHPV$UFKLWHFW
± 7HFKQLFDO0DQDJHU
± 62$
± ;DQG26)0RWLI

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 1
Nico Josuttis C++ Move Semantics

&0RYH6HPDQWLFV

0RWLYDWLRQ

& 
‹E\MRVXWWLVFRP

&RS\6HPDQWLFV

std::vector<std::string> coll;
[Link](3);
6WDFN +HDS

std::string s{getData()}; FROO



coll.push_back(s);

V
 G D W D ?

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 2
Nico Josuttis C++ Move Semantics

&RS\6HPDQWLFV

std::vector<std::string> coll;
[Link](3);
6WDFN +HDS

std::string s{getData()}; FROO



 
coll.push_back(s);

G D W D ?
V
 G D W D ?

& 
‹E\MRVXWWLVFRP

&RS\6HPDQWLFV ZLWK&&

std::vector<std::string> coll;
[Link](3);
6WDFN +HDS

std::string s{getData()}; FROO



  
coll.push_back(s);

G D W D  ?
coll.push_back(getData());
G D W D ?
V
 G D W D ?

JHW'DWD 
 G D W D  ?

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 3
Nico Josuttis C++ Move Semantics

0RYH6HPDQWLFV VLQFH&

std::vector<std::string> coll;
[Link](3);
6WDFN +HDS

std::string s{getData()}; FROO



  
coll.push_back(s);

coll.push_back(getData());
G D W D ?
V
 G D W D ?

JHW'DWD 
 G D W D  ?

& 
‹E\MRVXWWLVFRP

0RYH6HPDQWLFV VLQFH&

std::vector<std::string> coll;
[Link](3);
6WDFN +HDS

std::string s{getData()}; FROO


  
coll.push_back(s);

coll.push_back(getData());
G D W D ?
GHVWUXFW
WHPSRUDU\ V
 G D W D ?

JHW'DWD 
$YRLGREMHFWV  G D W D  ?
ZLWKQDPHV

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 4
Nico Josuttis C++ Move Semantics

&0RYH6HPDQWLFV

std::move()

& 
‹E\MRVXWWLVFRP

2EMHFWVZLWK1DPHV

‡ 2IWHQ\RXFDQ WDYRLGREMHFWVZLWKQDPHV
± :KHQ\RXQHHGDQREMHFWYDOXHPXOWLSOHWLPHV
std::string str{getData()};

coll1.push_back(str); FRS\ VWLOOQHHGWKHYDOXHRIstr
coll2.push_back(str); FRS\ EXWQRORQJHUQHHGWKHYDOXH

± :KHQ\RXGHDOZLWKSDUDPHWHUV
void reinit(std::string& s) {
history.push_back(s); FRS\ EXWQRORQJHUQHHGWKHYDOXH
s = getDefaultValue();
}

UHDGOLQHE\OLQHIURPP\6WUHDP DQGVWRUHWKHPDOOLQDFROOHFWLRQ
std::string row;
while (std::getline(myStream, row)) { UHDGQH[WOLQHLQWRrow
allRows.push_back(row); DQGFRS\ LWWRFROOHFWLRQRIDOOURZV
}

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 5
Nico Josuttis C++ Move Semantics

std::move() IRU2EMHFWVZLWK1DPHV

‡ std::move() "I no longer need this value here"


± :KHQ\RXQHHGDQREMHFWYDOXHPXOWLSOHWLPHV
std::string str{getData()};

coll1.push_back(str); FRS\ VWLOOQHHGWKHYDOXHRIstr
coll2.push_back(std::move(str)); PRYH RNQRORQJHUQHHGWKHYDOXH

± :KHQ\RXGHDOZLWKSDUDPHWHUV
void reinit(std::string& s) {
history.push_back(std::move(s)); PRYH RNQRORQJHUQHHGWKHYDOXH
s = getDefaultValue();
}

UHDGOLQHE\OLQHIURPP\6WUHDP DQGVWRUHWKHPDOOLQDFROOHFWLRQ
std::string row;
while (std::getline(myStream, row)) { UHDGQH[WOLQHLQWRrow
allRows.push_back(std::move(row)); DQGPRYH LWWRFROOHFWLRQRIDOOURZV
}

& 
‹E\MRVXWWLVFRP

3URFHVVLQJ0XOWLSOH7LPHV

std::vector<std::string> coll;
[Link](3);
6WDFN +HDS

std::string s{getData()}; FROO




  
coll.push_back(s);

coll.push_back(s); ZRXOGFRS\ DJDLQ G D W D ?

G D W D ?
V
 G D W D ?

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 6
Nico Josuttis C++ Move Semantics

std::move()

std::vector<std::string> coll;
[Link](3);
6WDFN +HDS

std::string s{getData()}; FROO



  
coll.push_back(s);

coll.push_back(std::move(s));
G D W D ?
V
I no longer need  G D W D ?
the value of s here

& 
‹E\MRVXWWLVFRP

9DOLGEXW8QVSHFLILHG6WDWH

std::vector<std::string> coll;
[Link](3);
6WDFN +HDS

std::string s{getData()}; FROO


  
coll.push_back(s);

coll.push_back(std::move(s));
G D W D ?
$PRYHGIURPOLEUDU\REMHFWLVLQ V
DYDOLGEXWXQVSHFLILHGVWDWH

"
 G D W D ?

std::cout << s; 2.VRPH YDOXH


K H O O R ?
int i = [Link](); 2.FRQVLVWHQWYDOXH
[Link]('.'); 2.VL]H ! 
char c1 = s[0]; 2.VRPH YDOXH
char c2 = s[5]; (UURU 8QGHI%HKDY 
s = "hello"; 2.VSHFLILHG VWDWH


& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 7
Nico Josuttis C++ Move Semantics

5HXVLQJ2EMHFWVDIWHUstd::move()

‡ <HVLWPDNHVVHQVHWRUHXVHREMHFWVDIWHUstd::move()
UHDGOLQHE\OLQHIURPP\6WUHDP DQGVWRUHLWLQDFROOHFWLRQ
std::vector<std::string> allRows;
std::string row;
while (std::getline(myStream, row)) { UHDGQH[WOLQHLQWRURZ
allRows.push_back(std::move(row)); DQGPRYH LWWRVRPHZKHUH
}

VZDSWZRVWULQJV
void swap(std::string& a, std::string& b) {
std::string tmp{std::move(a)};
a = std::move(b); DVVLJQQHZYDOXHWRPRYHGIURPa
b = std::move(tmp); DVVLJQQHZYDOXHWRPRYHGIURPb
}

& 
‹E\MRVXWWLVFRP

&0RYH6HPDQWLFV

59DOXH 5HIHUHQFHV

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 8
Nico Josuttis C++ Move Semantics

9HFWRUV:LWKRXW 0RYH6HPDQWLFV &

‡ &RQWDLQHUVKDYHYDOXHVHPDQWLFV
± 1HZHOHPHQWVDUHFRSLHGLQWRWKHFRQWDLQHU
± 3DVVHGDUJXPHQWVDUHQRWPRGLILHG
‡ 7KLVOHDGVWRXQQHFHVVDU\FRSLHVZLWK&&

template <typename T> std::vector<std::string> coll;


class vector { std::string s = getData();
public: 
 coll.push_back(s); FRS\ s LQWRFROO
FRS\HOHPLQWRWKHYHFWRU
void push_back(const T& elem); coll.push_back(getData()); FRS\ WHPSRUDU\LQWRFROO

XQQHFHVVDU\FRSLHV coll.push_back(s+s); FRS\ WHPSRUDU\LQWRFROO
XQQHFHVVDU\FRS\
LQ&&
coll.push_back(s); FRS\ s LQWRFROODJDLQ
};  QRORQJHUQHHGs
return coll;

& 
‹E\MRVXWWLVFRP

9HFWRUV:LWK 0RYH6HPDQWLFV &

‡ :LWKUYDOXHUHIHUHQFHV\RXFDQSURYLGHPRYH VHPDQWLFV
‡ 5YDOXHUHIHUHQFHVELQGWRUYDOXHV
± &DOOHUQRORQJHUQHHGVWKHYDOXH
± 0D\steal EXWNHHSYDOLG
#include <utility> GHFODUHVstd::move()

template <typename T> std::vector<std::string> coll;


class vector { std::string s = getData();
public: QRZQDPHG 
OYDOXHUHIHUHQFH
 coll.push_back(s); FRS\ s LQWRFROO
FRS\HOHPLQWRWKHYHFWRU
void push_back(const T& elem); coll.push_back(getData()); PRYH WHPSRUDU\LQWRFROO

PRYH HOHPLQWRWKHYHFWRU coll.push_back(s+s); PRYH WHPSRUDU\LQWRFROO
void push_back(T&& elem);
 coll.push_back(std::move(s)); PRYH s LQWRFROO
};  QRORQJHUQHHGs
GHFODUHV return coll;
UYDOXHUHIHUHQFH

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 9
Nico Josuttis C++ Move Semantics

6WULQJV:LWK0RYH6HPDQWLFV

‡ 0RYHVHPDQWLFVLVXVXDOO\LPSOHPHQWHGLQ
± DPRYHFRQVWUXFWRU
± DPRYHDVVLJQPHQWRSHUDWRU
DVRSWLPL]HGFRS\LQJ
± 6WHDOVE\NHHSLQJWKHVRXUFHYDOLG

class string {
private:
int len; FXUUHQWQXPEHURIFKDUDFWHUV
0RYHFRQVWUXFWRU
char* data; DUUD\RIFKDUDFWHUV XVHVUYDOXHUHIHUHQFH
public:
public: &RS\ FRQVWUXFWRUXVHV FUHDWHDFRS\ RIVZLWKLWVFRQWHQW PRYHG
FUHDWHDIXOOFRS\RIV FRQVWOYDOXHUHIHUHQFH string (string&& s)
string (const string& s) : len{[Link]}, FRS\OHQJWKDQG
: len{[Link]} { FRS\OHQJWK data{[Link]} { FRS\SRLQWHUWRPHPRU\
if (len > 0) { LIQRWHPSW\ [Link] = nullptr; HUDVHPHPRU\DWVRXUFH
data = new char[len+1];  QHZPHPRU\ WRUHDOO\PRYH RZQHUVKLS
memcpy(data, [Link],  FRS\FKDUV [Link] = 0;
len+1); }
} 
} };

& 
‹E\MRVXWWLVFRP

6WULQJV:LWK0RYH6HPDQWLFV
coll.push_back(x)

string x = "move"; string e1 = x;


x: s: e1:

OHQ  OHQ 
GDWD P R Y H ? GDWD P R Y H ?

class string { class string {


private: private:
int len; FXUUHQWQXPEHURIFKDUDFWHUV int len;
0RYHFRQVWUXFWRU
char* data; DUUD\RIFKDUDFWHUV XVHVUYDOXHUHIHUHQFH
public:
public: &RS\ FRQVWUXFWRUXVHV FUHDWHDFRS\ RIVZLWKLWVFRQWHQW PRYHG
FUHDWHDIXOOFRS\RIV FRQVWOYDOXHUHIHUHQFH string (string&& s)
string (const string& s) : len{[Link]}, FRS\OHQJWKDQG
: len{[Link]} { FRS\OHQJWK data{[Link]} { FRS\SRLQWHUWRPHPRU\
if (len > 0) { LIQRWHPSW\ [Link] = nullptr; HUDVHPHPRU\DWVRXUFH
data = new char[len+1];  QHZPHPRU\ WRUHDOO\PRYH RZQHUVKLS
memcpy(data, [Link],  FRS\FKDUV [Link] = 0;
len+1); }
} 
} };

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 10
Nico Josuttis C++ Move Semantics

6WULQJV:LWK0RYH6HPDQWLFV
coll.push_back(x) coll.push_back(std::move(e1))

string x = "move"; string e1 = x; string e2 = std::move(e1);


x: e1: s: e2:

OHQ  OHQ  OHQ 


GDWD P R Y H ? GDWD P R Y H ? GDWD

class string { class string {


private: private:
int len; FXUUHQWQXPEHURIFKDUDFWHUV int len;
0RYHFRQVWUXFWRU
char* data; DUUD\RIFKDUDFWHUV XVHVUYDOXHUHIHUHQFH
public:
public: &RS\ FRQVWUXFWRUXVHV FUHDWHDFRS\ RIVZLWKLWVFRQWHQW PRYHG
FUHDWHDIXOOFRS\RIV FRQVWOYDOXHUHIHUHQFH string (string&& s)
string (const string& s) : len{[Link]}, FRS\OHQJWKDQG
: len{[Link]} { FRS\OHQJWK data{[Link]} { FRS\SRLQWHUWRPHPRU\
if (len > 0) { LIQRWHPSW\ [Link] = nullptr; HUDVHPHPRU\DWVRXUFH
data = new char[len+1];  QHZPHPRU\ WRUHDOO\PRYH RZQHUVKLS
memcpy(data, [Link],  FRS\FKDUV [Link] = 0;
len+1); }
} 
} };

& 
‹E\MRVXWWLVFRP

6WULQJV:LWK0RYH6HPDQWLFV
coll.push_back(x) coll.push_back(std::move(e1))

string x = "move"; string e1 = x; string e2 = std::move(e1);


x: e1: s: e2:

OHQ  OHQ  OHQ 


GDWD P R Y H ? GDWD QS P R Y H ? GDWD

std::move(e1)
LVHTXLYDOHQWWR
static_cast<string&&>(e1)
class string {
private:
int len; FXUUHQWQXPEHURIFKDUDFWHUV
0RYHFRQVWUXFWRU
char* data; DUUD\RIFKDUDFWHUV XVHVUYDOXHUHIHUHQFH
public:
public: &RS\ FRQVWUXFWRUXVHV FUHDWHDFRS\ RIVZLWKLWVFRQWHQW PRYHG
FUHDWHDIXOOFRS\RIV FRQVWOYDOXHUHIHUHQFH string (string&& s)
string (const string& s) : len{[Link]}, FRS\OHQJWKDQG
: len{[Link]} { FRS\OHQJWK data{[Link]} { FRS\SRLQWHUWRPHPRU\
if (len > 0) { LIQRWHPSW\ [Link] = nullptr; HUDVHPHPRU\DWVRXUFH
data = new char[len+1];  QHZPHPRU\ WRUHDOO\PRYH RZQHUVKLS
memcpy(data, [Link],  FRS\FKDUV [Link] = 0;
len+1); }
} 
} };

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 11
Nico Josuttis C++ Move Semantics

2YHUORDGLQJRQ5HIHUHQFHV

‡ void foo(const Type&) UHDGRQO\DFFHVV


 LQSDUDPHWHUWRUHDG
± SDVVYDOXHZLWKRXWFUHDWLQJDFRS\
± FDQELQGWRHYHU\WKLQJ

‡ void foo(Type&) ZULWHDFFHVV


 LQ RXW SDUDPHWHU
± SDVVQDPHGHQWLW\WRUHWXUQDYDOXH
± RQO\QRQconst QDPHGREMHFW OYDOXHV

PRYHDFFHVV
‡ void foo(Type&&)  LQSDUDPHWHUWRDGRSW YDOXH
± SDVVYDOXHWKDWLVQRORQJHUQHHGHG
± RQO\ REMHFWVZLWKRXWQDPHRU ZLWKmove() UYDOXHV

‡ void foo(const Type&&) std::vector<std::string> coll;



± SRVVLEOHEXWVHPDQWLFFRQWUDGLFWLRQ const std::string s = getData();

± XVXDOO\FRYHUHGE\const Type&
coll.push_back(std::move(s)); FRSLHV
'RQ WXVHconst
LI\RXODWHUPRYH

& 
‹E\MRVXWWLVFRP

2YHUORDGLQJRQ5HIHUHQFHV

‡ void foo(const Type&) UHDGRQO\DFFHVV


 LQSDUDPHWHUWRUHDG
± SDVVYDOXHZLWKRXWFUHDWLQJDFRS\
± FDQELQGWRHYHU\WKLQJ

‡ void foo(Type&) ZULWHDFFHVV


 LQ RXW SDUDPHWHU
± SDVVQDPHGHQWLW\WRUHWXUQDYDOXH
± RQO\QRQconst QDPHGREMHFW OYDOXHV

PRYHDFFHVV
‡ void foo(Type&&)  LQSDUDPHWHUWRDGRSW YDOXH
± SDVVYDOXHWKDWLVQRORQJHUQHHGHG
± RQO\ REMHFWVZLWKRXWQDPHRU ZLWKmove() UYDOXHV

‡ void foo(const Type&&) std::vector<std::string> coll;



± SRVVLEOHEXWVHPDQWLFFRQWUDGLFWLRQ void insert(const std::string& s) {
± XVXDOO\FRYHUHGE\const Type& coll.push_back(std::move(s)); FRSLHV
}

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 12
Nico Josuttis C++ Move Semantics

2YHUORDGLQJRQ5HIHUHQFHV

‡ void foo(const Type&) UHDGRQO\DFFHVV


 LQSDUDPHWHUWRUHDG
± SDVVYDOXHZLWKRXWFUHDWLQJDFRS\
± FDQELQGWRHYHU\WKLQJ

‡ void foo(Type&) ZULWHDFFHVV


 LQ RXW SDUDPHWHU
± SDVVQDPHGHQWLW\WRUHWXUQDYDOXH
± RQO\QRQconst QDPHGREMHFW OYDOXHV

PRYHDFFHVV
‡ void foo(Type&&)  LQSDUDPHWHUWRDGRSW YDOXH
± SDVVYDOXHWKDWLVQRORQJHUQHHGHG
± RQO\ REMHFWVZLWKRXWQDPHRU ZLWKmove() UYDOXHV

‡ void foo(const Type&&) const std::string getValue(); IRUZDUGGHFO



± SRVVLEOHEXWVHPDQWLFFRQWUDGLFWLRQ std::vector<std::string> coll;

± XVXDOO\FRYHUHGE\const Type& coll.push_back(getValue()); FRSLHV
'RQ WXVHconst ZKHQ
UHWXUQLQJE\YDOXH

& 
‹E\MRVXWWLVFRP

%DVLFVRI0RYH6HPDQWLFV

‡ 0RYH6HPDQWLFVDOORZVWR
± RSWLPL]HFRS\LQJ
± E\VHPDQWLFDOO\VWHDOLQJUHVRXUFHVIURPDVRXUFH
± ,PSOHPHQWHGE\GHDOLQJZLWKUYDOXHUHIHUHQFHV type&&
$YRLGREMHFWV
ZLWKQDPHV
‡ ,GHDOO\VXSSRUWHGE\WHPSRUDU\REMHFWV
± &UHDWHWKHPRQWKHIO\ LQVWHDG
MyType x{42, "hello"};
‡ ZKHQSDVVLQJDUJXPHQWV foo(x); x QRORQJHUXVHG
‡ LQreturn VWDWHPHQWV
EHWWHU
foo(MyType{42,"hello"});

‡ std::move() RU
foo(std::move(x));
± VLJQDOVI no longer need this value here
± $PRYHGIURPREMHFWVLVLQDYDOLGEXWXQVSHFLILHGVWDWH
‡ $Q\RSHUDWLRQZLWKRXWDQ\DVVXPSWLRQDERXWWKHYDOXHLVILQH

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 13
Nico Josuttis C++ Move Semantics

&0RYH6HPDQWLFV

0RYH6HPDQWLFV
IRU
&ODVVHV

& 
‹E\MRVXWWLVFRP

%DVLF0RYH6XSSRUW

‡ *XDUDQWHHVIRUOLEUDU\REMHFWV †>OLEW\SHVPRYHGIURP@ 
± ³8QOHVVRWKHUZLVHVSHFLILHGPRYHGIURPREMHFWVVKDOOEHSODFHGLQD
YDOLGEXWXQVSHFLILHGVWDWH´

‡ &RS\DV)DOOEDFN
± ,IQRPRYHVHPDQWLFVLVSURYLGHGFRS\VHPDQWLFVLVXVHG
‡ <RXFDQGLVDEOHWKLVIDOOEDFN 8VHGE\0RYH2QO\7\SHVVXFKDV
VWGWKUHDGVWUHDPVVWGXQLTXHBSWU!

‡ 'HIDXOWPRYHRSHUDWLRQVDUHJHQHUDWHG
± 0RYHFRQVWUXFWRUDQGPRYHDVVLJQPHQWRSHUDWRU
‡ PRYHPHPEHUV
EXWRQO\LIWKLVFDQ WEHDSUREOHP
± 2QO\LIWKHUHLVQRXVHUGHFODUHGVSHFLDOPHPEHUIXQFWLRQ
‡ 1RFRS\FRQVWUXFWRU
‡ 1RDVVLJQPHQWRSHUDWRU
‡ 1RGHVWUXFWRU

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 14
Nico Josuttis C++ Move Semantics

0RYH6HPDQWLFVDQG6SHFLDO0HPEHU)XQFWLRQV
class Cust {
private:
std::string first;
std::string last;
int val;
public:
Cust(const std::string& f, const std::string& l, int v)
: first{f}, last{l}, val{v} {
}
QR FRS\FRQVWUXFWRU
‡ 0RYH VHPDQWLFV LVHQDEOHG
EHFDXVHQRRWKHUVSHFLDOPHPEHU
IXQFWLRQLVXVHUGHFODUHG
QR PRYHFRQVWUXFWRU ‡ 8QOHVVDPRYHLVQRWLPSOHPHQWDEOH

friend std::ostream& operator << (std::ostream& strm, const Cust& c) {


return strm << "[" << [Link] << ": " << [Link] << " " << [Link] << "]";
}
};

std::vector<Cust> v;
Cust c1{"Joe", "Fox", 77};
v.push_back(std::move(c1));  PRYHV c1
std::cout << "c1: " << c1 << '\n';  c1: [77: ??? ???]

& 
‹E\MRVXWWLVFRP

0RYH6HPDQWLFVDQG6SHFLDO0HPEHU)XQFWLRQV
class Cust {
private:
std::string first;
std::string last;
int val;
public:
Cust(const std::string& f, const std::string& l, int v)
: first{f}, last{l}, val{v} {
}
Cust(const Cust&) = default; FRS\FRQVWUXFWRU
‡ 0RYH VHPDQWLFV LVGLVDEOHG
EHFDXVHRIXVHUGHFODUHG
RWKHUVSHFLDOPHPEHUIXQFWLRQ
QR PRYHFRQVWUXFWRU ‡ &RS\LQJ XVHGDVIDOOEDFN

friend std::ostream& operator << (std::ostream& strm, const Cust& c) {


return strm << "[" << [Link] << ": " << [Link] << " " << [Link] << "]";
}
};

std::vector<Cust> v;
Cust c1{"Joe", "Fox", 77};
v.push_back(std::move(c1));  FRSLHV c1
std::cout << "c1: " << c1 << '\n';  c1: [77: Joe Fox]

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 15
Nico Josuttis C++ Move Semantics

0RYH6HPDQWLFVDQG6SHFLDO0HPEHU)XQFWLRQV
class Cust {
private: 0DUNPRYHFRQVWUXFWRUZLWKnoexcept
std::string first; LILPSOHPHQWHGDQGLWQHYHUWKURZV
std::string last;
int val;
public:
Cust(const std::string& f, const std::string& l, int v)
: first{f}, last{l}, val{v} {
}
Cust(const Cust& c) FRS\FRQVWUXFWRU 3DUDPHWHUc KDVQRPRYHVHPDQWLFV
: first{[Link]}, last{[Link]}, val{[Link]} { XQOHVVPDUNHGZLWKmove() DJDLQ
} WKHFDOOHUQRORQJHUQHHGVWKHYDOXH
EXWZHPLJKWQHHGLWPXOWLSOHWLPHV
Cust(Cust&& c) noexcept PRYHFRQVWUXFWRU
: first{std::move([Link])}, last{std::move([Link])}, val{[Link]} {
[Link] *= -1;
}
friend std::ostream& operator << (std::ostream& strm, const Cust& c) {
return strm << "[" << [Link] << ": " << [Link] << " " << [Link] << "]";
}
};

std::vector<Cust> v;
Cust c1{"Joe", "Fox", 77};
v.push_back(std::move(c1));  PRYHV c1
std::cout << "c1: " << c1 << '\n';  c1: [-77: ??? ???]

& 
‹E\MRVXWWLVFRP

5XOHVIRU6SHFLDO0HPEHU)XQFWLRQV

IRUFHV
GHIDXOW FRS\ FRS\ PRYH PRYH
GHVWUXFWRU
FRQVWUXFWRU FRQVWUXFWRU DVVLJQPHQW FRQVWUXFWRU DVVLJQPHQW

QRWKLQJ GHIDXOWHG GHIDXOWHG GHIDXOWHG GHIDXOWHG GHIDXOWHG GHIDXOWHG

DQ\
XQGHFODUHG GHIDXOWHG GHIDXOWHG GHIDXOWHG GHIDXOWHG GHIDXOWHG
FRQVWUXFWRU
GHIDXOW XVHU
GHIDXOWHG GHIDXOWHG GHIDXOWHG GHIDXOWHG GHIDXOWHG
XVHU GHFODUDWLRQ RI

FRQVWUXFWRU GHFODUHG
FRS\ XVHU XQGHFODUHG XQGHFODUHG
XQGHFODUHG GHIDXOWHG GHIDXOWHG
FRQVWUXFWRU GHFODUHG IDOOEDFNHQDEOHG IDOOEDFNHQDEOHG

FRS\ XVHU XQGHFODUHG XQGHFODUHG


GHIDXOWHG GHIDXOWHG GHIDXOWHG
DVVLJQPHQW GHFODUHG IDOOEDFNHQDEOHG IDOOEDFNHQDEOHG

PRYH XVHU XQGHFODUHG


XQGHFODUHG GHOHWHG GHOHWHG GHIDXOWHG
FRQVWUXFWRU GHFODUHG IDOOEDFNGLVDEOHG FDQ W
PRYH XVHU FRS\
GHIDXOWHG GHOHWHG GHOHWHG XQGHFODUHG GHIDXOWHG
DVVLJQPHQW IDOOEDFNGLVDEOHG GHFODUHG
XQGHFODUHG XQGHFODUHG XVHU
GHVWUXFWRU GHIDXOWHG GHIDXOWHG GHIDXOWHG IDOOEDFNHQDEOHG IDOOEDFNHQDEOHG GHFODUHG

$GRSWHGIURPKWWSIRRQDWKDQQHWVSHFLDOPHPEHUIXQFWLRQV
ZLWKIULHQGO\SHUPLVVLRQE\+RZDUG+LQQDQW

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 16
Nico Josuttis C++ Move Semantics

0RYH6HPDQWLFVLQ3RO\PRUSKLF&ODVVHV

‡ 'HFODUHGYLUWXDOGHVWUXFWRUVGLVDEOHPRYHVHPDQWLFV
± 0RYLQJVSHFLDOPHPEHUIXQFWLRQVDUHQRWJHQHUDWHG
± ,IDQGRQO\LIDSRO\PRUSKLFEDVHFODVVKDVPHPEHUV H[SHQVLYHWRFRS\
LWPLJKWPDNHVHQVHWRGHFODUHGHILQHPRYHRSHUDWLRQV
‡ 'RQ WGHFODUHGHVWUXFWRUVLQGHULYHGFODVVHV XQOHVV\RXKDYHWR
class Person { SRO\PRUSKLFEDVHFODVVZLWKYLUWXDOIXQFWLRQV
protected:
std::string id; WRVXSSRUWPRYHVHPDQWLFVIRUidGHFODUHPRYHIXQFWLRQV
public:

virtual void print() const = 0;
virtual ~Person() = default; GLVDEOHVPRYHVHPDQWLFVIRUPHPEHUV
};

class Customer : public Person { GHULYHGSRO\PRUSKLFFODVV


protected:
std::vector<int> data; PRYHVHPDQWLFVIRUdata HQDEOHGZLWKRXW VSHFLDOIXQFWLRQ
public:

virtual void print() const override;
virtual ~Customer() = default; GLVDEOHVPRYHVHPDQWLFVIRUPHPEHUV
};

& 
‹E\MRVXWWLVFRP

&0RYH6HPDQWLFV

3HUIHFW)RUZDUGLQJ

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 17
Nico Josuttis C++ Move Semantics

0RWLYDWLRQIRU3HUIHFW)RUZDUGLQJ

‡ 2YHUORDGLQJIRUconstQRQconst OYDOXHV DQGUYDOXHV

class C {

};
void foo(const C&); UHDGRQO\DFFHVV ELQGVWRDOOYDOXHV
void foo(C&); ZULWHDFFHVV ELQGVWRQRQconst OYDOXHV
void foo(C&&); PRYHDFFHVV ELQGVWRQRQconst UYDOXHV

C v;
const C c;
foo(v); FDOOVfoo(C&)
foo(c); FDOOVfoo(const C&)
foo(C{}); FDOOVfoo(C&&)
foo(std::move(v)); FDOOVfoo(C&&)

& 
‹E\MRVXWWLVFRP

0RWLYDWLRQIRU3HUIHFW)RUZDUGLQJ

‡ )RUZDUGPRYHVHPDQWLFVLQKHOSHUIXQFWLRQV
class C {

};
void foo(const C&); UHDGRQO\DFFHVV ELQGVWRDOOYDOXHV
void foo(C&); ZULWHDFFHVV ELQGVWRQRQconst OYDOXHV
void foo(C&&); PRYHDFFHVV ELQGVWRQRQconst UYDOXHV
void callFoo(const C& x) {
foo(x); x LVconst OYDOXH !FDOOVfoo(const C&)
}
void callFoo(C& x) {
foo(x); [LVQRQconst OYDOXH !FDOOVfoo(C&)
}
void callFoo(C&& x) {
foo(std::move(x)); x LVQRQconst OYDOXH !QHHGVstd::move() WRFDOOfoo(C&&)
}
XVHstd::move() WRIRUZDUGPRYHVHPDQWLFV
C v;
const C c;
callFoo(v); FDOOVfoo(C&)
callFoo(c); FDOOVfoo(const C&)
callFoo(C{}); FDOOVfoo(C&&)
callFoo(std::move(v)); FDOOVfoo(C&&)

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 18
Nico Josuttis C++ Move Semantics

3HUIHFW)RUZDUGLQJ

‡ 3HUIHFWIRUZDUGLQJRISDUDPHWHUV
 7HPSODWHSDUDPHWHU
 'HFODULQJWKHSDUDPHWHUDV&&
class C { RIWKHWHPSODWHSDUDPHWHU

3. std::forward<>()
};
void foo(const C&); UHDGRQO\DFFHVV ELQGVWRDOOYDOXHV
void foo(C&); ZULWHDFFHVV ELQGVWRQRQconstUniversal
OYDOXHV / forwarding reference
void foo(C&&); PRYHDFFHVV ELQGVWRQRQconstFRPPXQLW\&VWDQGDUGWHUP
UYDOXHV
‡ &DQUHIHUWRconst DQGQRQconst
void callFoo(const C& x) {
foo(x);<typename T>
template x LVconst OYDOXH ‡ &DQUHIHUWRUYDOXHDQGOYDOXH
!FDOOVfoo(const C&)
}
void callFoo(T&& x) x LVDuniversal RUforwarding UHIHUHQFH
void callFoo(C& x) {
{
foo(x); [LVQRQconst OYDOXH !FDOOVfoo(C&)
} foo(std::forward<T>(x)); SHUIHFWO\IRUZDUGVPRYHVHPDQWLFV
}
void callFoo(C&& x) {
foo(std::move(x)); std::forward<>()
x LVQRQconst LV
OYDOXH !QHHGVstd::move() WRFDOOfoo(C&&)
} std::move() RQO\IRUUYDOXHV

C v;
const C c;
callFoo(v); foo(std::forward<T>(x)) !foo(x)
callFoo(c); foo(std::forward<T>(x)) !foo(x)
callFoo(C{}); foo(std::forward<T>(x)) !foo(std::move(x))
callFoo(std::move(v)); foo(std::forward<T>(x)) !foo(std::move(x))

& 
‹E\MRVXWWLVFRP

7KH7ZR0HDQLQJVRI&& 'HFODUDWLRQV

‡ GHFODUHV
± )RUW\SHV UDZ UYDOXHUHIHUHQFHV
± )RUWHPSODWHSDUDPVXQLYHUVDOIRUZDUGLQJUHIHUHQFHV
class Type { class Type {
 
}; };

template<typename T>
void foo(Type&& x) UYDOXH UHIHUHQFH void foo(T&& x) XQLYHUVDO UHIHUHQFH
{ {
std::is_const<Type>::value DOZD\V IDOVH std::is_const<T>::value PD\EHWUXHRUIDOVH
 
SHUIHFWO\IRUZDUGx SHUIHFWO\IRUZDUGx
bar(std::move(x)); bar(std::forward<T>(x));
x KDVYDOLGEXWXQVSHFLILHGVWDWH x KDVYDOLGEXWXQVSHFLILHGVWDWH
} }

Type v; Type v;
const Type c; const Type c;

foo(v); (5525 foo(v); 2.x LVQRQFRQVW


foo(c); (5525 foo(c); 2.x LVFRQVW
foo(Type{}); 2. foo(Type{}); 2.x LVQRQFRQVW
foo(std::move(v)); 2. foo(std::move(v)); 2.x LVQRQFRQVW

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 19
Nico Josuttis C++ Move Semantics

8VLQJ*HQHUDWHGDQG,PSOHPHQWHG0RYH6HPDQWLFV
GDWDVHJPHQW cv:
$UW $UW
$UW $UW
/HH PRYHV /HH
/HH /HH
 


class Cust {
private:
std::string first;
std::string last;
int val;
public:
Cust(const std::string& f, const std::string& l, int v)
: first{f}, last{l}, val{v} {
}
QRVSHFLDOPHPEHUIXQFWLRQV
};


std::vector<Cust> cv;

cv.push_back(Cust{"Art","Lee",42}); FUHDWH FXVWRPHUDQG FRS\PRYH LWLQWRcv

& 
‹E\MRVXWWLVFRP

3HUIHFW)RUZDUGLQJZLWK(PSODFH)XQFWLRQV
GDWDVHJPHQW cv:
$UW $UW
$UW $UW
/HH PRYHV /HH
/HH /HH
 
 -LO
-LO PRYHV &RRN
class Cust { -LO

private: &RRN FRSLHV
&RRN
std::string first;

std::string last;
int val;
public:
Cust(const std::string& f, const std::string& l, int v)
: first{f}, last{l}, val{v} {
}
QRVSHFLDOPHPEHUIXQFWLRQV
};


std::vector<Cust> cv;
cv.push_back(Cust{"Art","Lee",42}); FUHDWH FXVWRPHUDQG FRS\PRYH LWLQWRFY
std::string first{"Jil"};
std::string last{"Cook"};
cv.emplace_back(std::move(first), last, 39); FUHDWH QHZFXVWRPHULQVLGHFY

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 20
Nico Josuttis C++ Move Semantics

3HUIHFW)RUZDUGLQJZLWK(PSODFH)XQFWLRQV
GDWDVHJPHQW cv:
$UW $UW
$UW $UW
/HH PRYHV /HH
/HH /HH
 
 -LO
-LO PRYHV &RRN
-LO

&RRN FRSLHV
&RRN


template <typename T, >


class vector {
public: 9DULDGLFWHPSODWHRIXQLYHUVDOIRUZDUGLQJUHIHUHQFHV
 WRSHUIHFWO\IRUZDUGHDFKDUJXPHQW
template<typename... Args>
void emplace_back(Args&&... args) {


place_element_in_memory(T(std::forward<Args>(args)...));
}

};

std::string first{"Jil"};
std::string last{"Cook"};
cv.emplace_back(std::move(first), last, 39); FUHDWH QHZFXVWRPHULQVLGHFY

& 
‹E\MRVXWWLVFRP

3HUIHFW3DVVLQJZLWKauto&&

‡ 7RSHUIHFWIRUZDUGDUHWXUQYDOXH
± GHFODUHUHWXUQHGYDOXHDVauto&&
‡ 8QLYHUVDOIRUZDUGLQJUHIHUHQFHZLWKRXWEHLQJDWHPSODWHSDUDPHWHU
± DQGIRUZDUG

‡ )RUH[DPSOH
SDVVUHWXUQYDOXHRIFRPSXWH WRSURFHVV 
process(compute(t)); 2.SHUIHFW

1RWH$UHIHUHQFH
H[WHQGVWKHOLIHWLPH
RIDWHPSRUDU\

VDPHEXWGRLQJVRPHWKLQJEHWZHHQFRPSXWH DQGSURFHVV 
auto&& val = compute(t);

process(std::forward<decltype(val)>(val));

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 21
Nico Josuttis C++ Move Semantics

auto&& DV8QLYHUVDO)RUZDUGLQJ5HIHUHQFH

‡ 5HIHUHQFHWKDW
± FDQuniversally UHIHU
‡ WRWHPSRUDU\REMHFWVDQGREMHFWVPDUNHGZLWKmove() UYDOXHV
‡ WRQDPHGREMHFWV OYDOXHV
± NHHSV LWVQRQFRQVWQHVV
± LVXVHIXOIRUperfect forwarding
std::string returnTmpString();
const std::string& returnConstStringRef();
std::string s{"some lvalue"}; const auto&
FDQUHIHUWRHYHU\WKLQJEXW const
const auto& s1 = s; 2.VLVFRQVW
const auto& s2 = returnTmpString(); 2.VLVFRQVW
const auto& s3 = returnConstStringRef(); 2.VLVFRQVW auto&
FDQQRW UHIHUWRHYHU\WKLQJ
auto& s4 = s; 2.VLVQRWFRQVW
auto& s5 = returnTmpString(); (5525FDQQRWELQGQRQFRQVWOYDOXHUHIHUHQFHWRUYDOXH
auto& s6 = returnConstStringRef(); 2.VLVFRQVW

auto&& s7 = s; 2.VLVQRWFRQVW auto&&


auto&& s8 = returnTmpString(); 2.VLVQRWFRQVW FDQ UHIHUWRHYHU\WKLQJ
DQGNHHSVQRQFRQVWQHVV
auto&& s9 = returnConstStringRef(); 2.VLVFRQVW

& 
‹E\MRVXWWLVFRP

&8QLYHUVDOIRUZDUGLQJ5HIHUHQFHVIRU5DQJHVDQG9LHZV

‡ const YLHZVPLJKWQRWVXSSRUWLWHUDWLQJ
± 7KH\PLJKWKDYHWRPRGLI\WKHLUVWDWHZKLOHLWHUDWLQJ
± 8VHXQLYHUVDOIRUZDUGLQJUHIHUHQFHVZKHQSDVVHGE\UHIHUHQFH

template<typename T> %HWWHU


void print(const T& coll) { template<typename T>
for (const auto& elem : coll) { void printElems(T&& coll)
std::cout << elem << '\n'; RU
}
void printElems(auto&& coll)
}

std::vector vec{1, 2, 3, 4, 5};


print(vec); 2.
print(vec | std::views::drop(3)); 2.
print(vec | std::views::filter()); (5525 ZLWKRXWXQLYHUVDOUHIHUHQFH
std::list lst{1, 2, 3, 4, 5}; 2.
print(lst | std::views::drop(3)); (5525 ZLWKRXWXQLYHUVDOUHIHUHQFH

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 22
Nico Josuttis C++ Move Semantics

7KDQN<RX

)LUVWGUDIWLVRXW
FSSVWGFRP

1LFRODL0-RVXWWLV

ZZZMRVXWWLVFRP
QLFR#MRVXWWLVFRP
#1LFR-RVXWWLV

& 
‹E\MRVXWWLVFRP

@CppCon2021 2021-10-27 23

You might also like