C++11 supports move semantics.
One: Why you need to move semantics and what is moving semantics
Let's take a look at the replication process before c++11. Suppose you have the following code:
Vector<string> v1 (1000000);//v1 holds 100W of string, assuming each string length is 1000
Vector<string> v2 (v1);//Use V1 to initialize V2
Both the vector and the string classes use dynamic memory allocations, so they must define a copy constructor that uses their own new version.
The copy constructor vector<string> will use new to assign the object to 1000W strings, and each string will use new to allocate a 1000-character space size to each string. The next step is to copy the string from V1 to V2, where the workload is very large, but there is no problem.
But is it really not a problem? Sometimes the answer is negative. For example, suppose you have a function that returns a Vector<string> object.
Vector<string>copyvector (const vector<string> &v) {
Vector<string> temp;
Copy 100W string to Temp
return temp;
}
Next, call this function in the following way.
vector<string> v1 (1000000); The //v1 stores 100W strings, assuming that each string is a length of
Vector<string> V2=copyvector (v1);//Use V1 to initialize V2
When constructing the V2, the compiler first generates a temp copy with the V1 construct, then copies the temp to a temporary object and returns it to V2,v2 to construct itself with the temporary object.
This will result in a very large workload! Did a lot of hard work ( copy temp to a temporary object and return it to v2,v2 to use the temporary object to construct itself ). After that, temp's temporary object was deleted, and the temp copy that was returned was deleted, and if the compiler was able to transfer the ownership of temp directly to V2, wouldn't it be better? That is, instead of copying the 100W string multiple times to a new place and then deleting the original character, the character is reserved and associated with the V2. This is similar to the movement of files in your computer. The actual files are still in place, but only the records have been modified, and this method is called moving semantics .
Moving semantics avoids moving the original data, but only modifies the record.
to implement the move semantics, you must let the compiler know when to replicate and when not to replicate. This is where rvalue references are most useful .
Two: How to implement the moving semantics
See a simple example of using the move semantics.
1#include <iostream>
2usingnamespaceStd
3classa{
4Private:
5intData//Data
6int*pi;//Point to data
7 Public:
8//Suppress implicit conversions
9A () {
Ten}
OneExplicitAinti):d ata (i) {
Acout<<"Normal constuctor!"<<endl;
-pi=&data;
-}
theAConstA &a) {
-Data=a.data;
-cout<<"Copy constructor!"<<endl;
-pi=&data;
+}
-
+A (a &&a) {
Acout<<"Move constructor!"<<endl;
at//move A.pi directly to Pi
-Pi=a.pi;
-//Modify Source Pi
-A.pi=nullptr;
-A.data=0;
-}
in//A (a &&a) =delete;
-Aoperator+(ConstA &a) {
toA temp (data+a.data);
+cout<<endl<<"operator+ called!show temp!"<<endl;
-Temp.show ();
thecout<<endl;
* returnTemp
$}
Panax NotoginsengvoidShow ()Const{
-cout<<"pi="<<pi<<"data="<<data<<endl;
the}
+};
A
theintMain ()
+{
-intI= About;
$A A (Ten);
$A.show ();
-A b (i);
-B.show ();
theA C (b);
-C.show ();
WuyiA d (B+C);
thecout<<"Show d!"<<endl;
-D.show ();
Wu
-
About }
Run:
See what the problem is?
Yes, it does not seem to call the move constructor !
But have you found!temp and D Pi all pointing to the same place? What's the situation?
It turns out that GCC comes with the right value semantics!
That is, the compiler GCC will help you optimize automatically!
Please see the example below! We take advantage of C++11 's delete feature!
#include <iostream>
usingnamespaceStd
classa{
Private:
intData//Data
int*pi;//Point to data
Public:
//Suppress implicit conversions
A () {
}
ExplicitAinti):d ata (i) {
cout<<"Normal constuctor1!"<<endl;
pi=&data;
}
AConstA &a) {
Data=a.data;
cout<<"Copy constructor!"<<endl;
pi=&data;
}
/*
A (a &&a) {
cout<< "Move constructor!" <<endl;
Move A.pi directly to Pi
Pi=a.pi;
Modify Source Pi
A.pi=nullptr;
a.data=0;
}*/
A (a &&a) =delete;
Aoperator+(ConstA &a) {
A temp (data+a.data);
cout<<endl<<"operator+ called!show temp!"<<endl;
Temp.show ();
cout<<endl;
returnTemp
}
voidShow ()Const{
cout<<"pi="<<pi<<"data="<<data<<endl;
}
};
intMain () {
intI= About;
A A (Ten);
A.show ();
A b (i);
B.show ();
A C (b);
C.show ();
A d (B+C);
cout<<"Show d!"<<endl;
D.show ();
}Operation Result:
In other words, a (a&&) constructor will be called on return temp;
But now this function has been explicitly deleted by us!
B+c is also a right value! It is also necessary to call the move constructor!
So the last example is actually a constructor that calls the move semantics!
=================================================================================
So what about Microsoft's compilers?
When is C + + one move constructor called?