Skip to content

Instantly share code, notes, and snippets.

@steveash
Created November 5, 2016 15:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steveash/3da817c58b47d324d074dfe0227d475b to your computer and use it in GitHub Desktop.
Save steveash/3da817c58b47d324d074dfe0227d475b to your computer and use it in GitHub Desktop.
c++11 quick reminder on lvalue/rvalue and move vs copy
// 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