C++ Move Semantics Overview
C++ Move Semantics Overview
&
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
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
G D W D ?
V
G D W D ?
&
E\MRVXWWLVFRP
&RS\6HPDQWLFV ZLWK&&
std::vector<std::string> coll;
[Link](3);
6WDFN +HDS
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
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
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
± :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
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
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
coll.push_back(std::move(s));
G D W D ?
$PRYHGIURPOLEUDU\REMHFWLVLQ V
DYDOLGEXWXQVSHFLILHGVWDWH
"
G D W D ?
&
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
&RQWDLQHUVKDYHYDOXHVHPDQWLFV
± 1HZHOHPHQWVDUHFRSLHGLQWRWKHFRQWDLQHU
± 3DVVHGDUJXPHQWVDUHQRWPRGLILHG
7KLVOHDGVWRXQQHFHVVDU\FRSLHVZLWK&&
&
E\MRVXWWLVFRP
:LWKUYDOXHUHIHUHQFHV\RXFDQSURYLGHPRYH VHPDQWLFV
5YDOXHUHIHUHQFHVELQGWRUYDOXHV
± &DOOHUQRORQJHUQHHGVWKHYDOXH
± 0D\steal EXWNHHSYDOLG
#include <utility> GHFODUHVstd::move()
&
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)
OHQ OHQ
GDWD P R Y H ? GDWD P R Y H ?
&
E\MRVXWWLVFRP
@CppCon2021 2021-10-27 10
Nico Josuttis C++ Move Semantics
6WULQJV:LWK0RYH6HPDQWLFV
coll.push_back(x) coll.push_back(std::move(e1))
&
E\MRVXWWLVFRP
6WULQJV:LWK0RYH6HPDQWLFV
coll.push_back(x) coll.push_back(std::move(e1))
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
PRYHDFFHVV
void foo(Type&&) LQSDUDPHWHUWRDGRSW YDOXH
± SDVVYDOXHWKDWLVQRORQJHUQHHGHG
± RQO\ REMHFWVZLWKRXWQDPHRU ZLWKmove() UYDOXHV
&
E\MRVXWWLVFRP
2YHUORDGLQJRQ5HIHUHQFHV
PRYHDFFHVV
void foo(Type&&) LQSDUDPHWHUWRDGRSW YDOXH
± SDVVYDOXHWKDWLVQRORQJHUQHHGHG
± RQO\ REMHFWVZLWKRXWQDPHRU ZLWKmove() UYDOXHV
&
E\MRVXWWLVFRP
@CppCon2021 2021-10-27 12
Nico Josuttis C++ Move Semantics
2YHUORDGLQJRQ5HIHUHQFHV
PRYHDFFHVV
void foo(Type&&) LQSDUDPHWHUWRDGRSW YDOXH
± SDVVYDOXHWKDWLVQRORQJHUQHHGHG
± RQO\ REMHFWVZLWKRXWQDPHRU ZLWKmove() UYDOXHV
&
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
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
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
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
$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
};
&
E\MRVXWWLVFRP
&0RYH6HPDQWLFV
3HUIHFW)RUZDUGLQJ
&
E\MRVXWWLVFRP
@CppCon2021 2021-10-27 17
Nico Josuttis C++ Move Semantics
0RWLYDWLRQIRU3HUIHFW)RUZDUGLQJ
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;
&
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
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
&
E\MRVXWWLVFRP
&8QLYHUVDOIRUZDUGLQJ5HIHUHQFHVIRU5DQJHVDQG9LHZV
const YLHZVPLJKWQRWVXSSRUWLWHUDWLQJ
± 7KH\PLJKWKDYHWRPRGLI\WKHLUVWDWHZKLOHLWHUDWLQJ
± 8VHXQLYHUVDOIRUZDUGLQJUHIHUHQFHVZKHQSDVVHGE\UHIHUHQFH
&
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