#include<iostream>
#include<stdio.h>
using namespace std;
class Test
{
public:
string n;
Test():n("test") {}
};
int main()
{
Test t1;
std::cout<<"before move"<<"\n";
std::cout<<"t1.n=" << t1.n<<"\n";
Test t2=std::move(t1);
std::cout<<"after move"<<"\n";
std::cout<<"t1.n="<<t1.n<<"\n";
std::cout<<"t2.n="<<t2.n<<"\n";
return 0;
}
Output of the above program produces below result
before move t1.n=test after move t1.n= t2.n=test
Understood that, after moving the object t1 to t2, value of t2.n results as empty string
But the same concept move concept doesn't work with integer.
#include<iostream>
#include<stdio.h>
using namespace std;
class Test
{
public:
int n;
Test():n(5) {}
};
int main()
{
Test t1;
std::cout<<"before move"<<"\n";
std::cout<<"t1.n=" << t1.n<<"\n";
Test t2=std::move(t1);
std::cout<<"after move"<<"\n";
std::cout<<"t1.n="<<t1.n<<"\n";
std::cout<<"t2.n="<<t2.n<<"\n";
return 0;
}
Output of the above program produces below result
before move t1.n=5 after move t1.n=5 t2.n=5
After moving the object t1 to t2, i expected the value of t2.n as 0 but the old value still exists.
Can someone please explain the concept behind this behavior.
In general, a moved-from object can have any value which is valid for its type. For example, a moved-from std::string
may become empty, or it may be something completely different. It might sometimes be empty and sometimes not. There is no restriction on what it can be, and the exact value should not be relied upon.
Since the moved-from object can be in any valid state, we can see that copying an object is a valid way of moving it. In fact, for any type which does not define a move constructor, the copy constructor will be used instead when moving the object. std::move
does not require the moved-from object to become empty (a concept that we can't necessarily define for all types). Of course, copying may not be the most efficient way to move an object, but it is allowed. Primitive types basically capitalise on this, so moving a primitive type is equivalent to copying it.
I'd like to reemphasise this: do not (generally) rely on the value of a moved-from object. It is not usually a specified value. Do not assume that a moved-from object is the same as a default-constructed object. Do not assume it to be any other value. Some specific types such as int
or the standard smart pointer types may specify the moved-from value, but these are special cases and do not define the general rule. It is generally wise to not use a moved-from object until you copy a known value into it.
Moving in C++ is what is called shallow copy in other languages.
copy: If an object stores data in dynamically allocated memory, then a (deep) copy implies (1) allocating an equivalent block of memory and (2) copying all elements from one block to the other. This preserves the copied-from object and creates a new, completely independent copy.
move: If the same object is moved, then only the data actually stored with the object (but not the data stored in the dynamically allocated memory) are copied over (actually, they are moved over, i.e. this is recursive), i.e. the pointer variable holding the address of the memory block and information about the size. At the same time, the moved-from object is 'emptied', i.e. put into a (valid) state which upon destruction does not affect the moved-to object. This implies that the
pointer to the memory block of the moved-from object must be reset to nullptr
and the variables referring to the size of memory be reset to zero, the process you called emptying.
Now, for objects that don't use dynamically allocated memory, in particular all builtin types (such as int
), there is no difference between moving and copying. In particular, leaving the moved-from variable in its original state, i.e. making a copy, is just fine and actually demanded by the standard. (The standard could have left this unspecified or demand a reset to a default value, i.e. 0, but that's not how things are.)
See also here for a loooong description of move semantics.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With