Created
November 5, 2016 15:39
-
-
Save steveash/3da817c58b47d324d074dfe0227d475b to your computer and use it in GitHub Desktop.
c++11 quick reminder on lvalue/rvalue and move vs copy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// given a temp object like this: | |
class Temp | |
{ | |
public: | |
Temp() : idx(0), good(true) | |
{ | |
AL_INFO << "Temp zero-argo ctor " << idx; | |
} | |
~Temp() | |
{ | |
AL_INFO << "Temp dtor " << idx << " good " << good; | |
good = false; | |
} | |
explicit Temp(int idx) | |
: idx(idx), good(true) | |
{ | |
AL_INFO << "Temp explicit ctor " << idx; | |
} | |
Temp(const Temp& other) | |
{ | |
AL_INFO << "Temp copy ref ctor " << idx << " to " << other.idx; | |
idx = other.idx; | |
good = other.good; | |
} | |
Temp(Temp&& other) | |
{ | |
AL_INFO << "Temp move ctor from " << idx << " to " << other.idx; | |
idx = other.idx; | |
//other.idx = 0; | |
good = other.good; | |
other.good = false; | |
} | |
Temp& operator=(const Temp& other) | |
{ | |
if (this == &other) | |
return *this; | |
AL_INFO << "Temp copy assignment from " << idx << " to " << other.idx; | |
idx = other.idx; | |
good = other.good; | |
return *this; | |
} | |
Temp& operator=(Temp&& other) | |
{ | |
if (this == &other) | |
return *this; | |
AL_INFO << "Temp move assignment from " << idx << " to " << other.idx; | |
idx = other.idx; | |
good = other.idx; | |
//other.idx = 0; | |
other.good = false; | |
return *this; | |
} | |
bool good = false; | |
int idx = 0; | |
}; | |
// ... | |
// and some code like this: | |
{ | |
AL_INFO << "about to create holder"; | |
std::vector<Temp> holder; | |
auto tmp1 = Temp{ 1 }; // happens as a move | |
// transfer ownership; without the move() this would be lvalue to rvalue which | |
// does a copy-ref | |
holder.push_back(std::move(tmp1)); | |
// this is always rvalue to rvalue to the move isn't necessary but i think it | |
// reads the intention better? | |
holder.push_back(std::move(Temp(2))); | |
holder.push_back(std::move(Temp(3))); | |
// if you just used the auto and not auto& this would be a copy-assign | |
AL_INFO << "about to get by ref"; | |
auto& second = holder[1]; | |
// iteration over const refs means no copy obviously | |
for (const auto& it : holder) | |
{ | |
AL_INFO << " iterating " << it.idx; | |
} | |
AL_INFO << " about to leave the block"; | |
} | |
AL_INFO << "left block"; | |
// at this point only destructors for 1, 2, 3 called once like you want | |
/* | |
OUTPUT | |
about to create holder | |
Temp explicit ctor 1 | |
Temp move ctor from 0 to 1 | |
Temp explicit ctor 2 | |
Temp move ctor from 0 to 1 | |
Temp dtor 1 good false | |
Temp move ctor from 0 to 2 | |
Temp dtor 2 good false | |
Temp explicit ctor 3 | |
Temp move ctor from 0 to 1 | |
Temp move ctor from 0 to 2 | |
Temp dtor 1 good false | |
Temp dtor 2 good false | |
Temp move ctor from 0 to 3 | |
Temp dtor 3 good false | |
about to get by ref | |
index1 is 2 | |
iterating 1 | |
iterating 2 | |
iterating 3 | |
about to leave the block | |
Temp dtor 1 good false | |
Temp dtor 1 good true | |
Temp dtor 2 good true | |
Temp dtor 3 good true | |
left block | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment