C ++ 11 right value reference and std: move statement instance parsing, right value std
Keywords: C ++ 11, right value reference, rvalue, std: move, VS 2015
OS: Windows 10
Right-value reference (and supported Move semantics and perfect forwarding) is one of the most important language features added to C ++ 0x. From a practical perspective, it can perfectly solve the temporary object efficiency problem that has been criticized for a long time in C ++. In terms of language itself, it improves the defects of the reference type in C ++ in the left and right values. From the perspective of the Database Designer, it brings a powerful tool to the Database Designer. From the perspective of database users, the "free" efficiency can be improved without moving to the ground...
The following example is used to explore the right value reference in depth.
1. What is the left value, what is the right value, simply put, the left value can be assigned, and the right value cannot be assigned. The following code is used as an example. "A = getA ();" indicates that the return value of a is the left value and the return value of getA () indicates the right value.
#include "stdafx.h"#include <iostream>class A{public: A() { std::cout << "Constructor" << std::endl; } A(const A&) { std::cout << "Copy Constructor" << std::endl; } ~A() {}};static A getA(){ A a; return a;}int main(){ A a = getA(); return 0;}
Run the above Code and the output result is as follows:
ConstructorCopy Constructor
We can see that the constructor of A is called once, and the copy constructor is called once. constructor and copy constructor consume A lot. Can we avoid copying constructor here? C ++ 11 has done this.
2. Add A mobile constructor. The Code is as follows:
#include "stdafx.h"#include <iostream>class A{public: A() { std::cout << "Constructor" << std::endl; } A(const A&) { std::cout << "Copy Constructor" << std::endl; } A(const A&&) { std::cout << "Move Constructor" << std::endl; } ~A() {}};static A getA(){ A a; return a;}int main(){ A a = getA(); return 0;}
Run the above Code and output the result:
ConstructorMove Constructor
In this way, the mobile constructor is called instead of the copy constructor. Here we do not see the advantages of mobile construction.
3. modify the code and add A member variable to Class A as follows:
#include "stdafx.h"#include <iostream>#include <vector>class B{public: B() {} B(const B&) { std::cout << "B Constructor" << std::endl; }};class A{public: A(): m_b(new B()) { std::cout << "A Constructor" << std::endl; } A(const A& src) : m_b(new B(*(src.m_b))) { std::cout << "A Copy Constructor" << std::endl; } A(A&& src) : m_b(src.m_b) { src.m_b = nullptr; std::cout << "A Move Constructor" << std::endl; } ~A() { delete m_b; }private: B* m_b;};static A getA(){ A a; std::cout << "================================================" << std::endl; return a;}int main(){ A a = getA(); std::cout << "================================================" << std::endl; A a1(a); return 0;}
Run the above Code and output the result:
A Constructor================================================A Move Constructor================================================B ConstructorA Copy Constructor
"A a = getA ();" calls the mobile structure of a. "A a1 (a);" calls the copy structure of. The copy structure of a requires A deep copy of member variable B, while the moving STRUCTURE OF A does not. Obviously, the moving construction efficiency of A is high.
4. the std: move statement can change the left value to the right value to avoid copying the structure. The modification code is as follows:
#include "stdafx.h"#include <iostream>#include <vector>class B{public: B() {} B(const B&) { std::cout << "B Constructor" << std::endl; }};class A{public: A(): m_b(new B()) { std::cout << "A Constructor" << std::endl; } A(const A& src) : m_b(new B(*(src.m_b))) { std::cout << "A Copy Constructor" << std::endl; } A(A&& src) : m_b(src.m_b) { src.m_b = nullptr; std::cout << "A Move Constructor" << std::endl; } ~A() { delete m_b; }private: B* m_b;};static A getA(){ A a; std::cout << "================================================" << std::endl; return a;}int main(){ A a = getA(); std::cout << "================================================" << std::endl; A a1(a); std::cout << "================================================" << std::endl; A a2(std::move(a1)); return 0;}
Run the above Code and output the result:
A Constructor================================================A Move Constructor================================================B ConstructorA Copy Constructor================================================A Move Constructor
"A a2 (std: move (a1);" converts a1 to the right value, so a2 calls the move constructor instead of the copy constructor.
5. The assignment operator can also be a move assignment.
# Include "stdafx. h "# include <iostream >#include <vector> class B {public: B () {} B (const B &) {std :: cout <"B Constructor" <std: endl ;}; class A {public: A (): m_ B (new B () {std :: cout <"A Constructor" <std: endl;} A (const A & src): m_ B (new B (* (src. m_ B) {std: cout <"A Copy Constructor" <std: endl;} A (A & src): m_ B (src. m_ B) {src. m_ B = nullptr; std: cout <"A Move Constructor" <std :: Endl;} A & operator = (const A & src) {if (this = & src) return * this; m_ B = new B (* (src. m_ B); std: cout <"operator = (const A & src)" <std: endl; return * this ;} A & operator = (A & src) {if (this = & src) return * this; m_ B = src. m_ B; src. m_ B = nullptr; std: cout <"operator = (const A & src)" <std: endl; return * this ;}~ A () {delete m_ B;} private: B * m_ B;}; static A getA () {A a A; std :: cout <"======================================== ============== "<std:: endl; return a;} int main () {A a = getA (); // move the constructed std :: cout <"======================================== ============== "<std:: endl; A a1 (a); // copy the structure std :: cout <"======================================== ============== "<std:: endl; A a2 (std: move (a1); // move to construct std :: cout <"======================================== ============== "<std:: endl; a2 = getA (); // move the value std :: cout <"======================================== ============== "<std:: endl; a2 = a1; // copy value: return 0 ;}
Run the above Code and output the result:
A Constructor================================================A Move Constructor================================================B ConstructorA Copy Constructor================================================A Move Constructor================================================A Constructor================================================A Move Constructoroperator=(const A&& src)================================================B Constructoroperator=(const A& src)
In short, try to add a mobile constructor and a mobile assignment function to the class to reduce the consumption of copy construction and copy assignment.
Reference the right value (and its supported
Move
Meaning and perfect forwarding) Yes
C ++ 0x
Major notes to be added
This is from the proposal of this feature in
C ++-State of the Evolution
High on the list
You can also see the top spot. From a practical point of view, it can be perfectly solved
C ++
Long-standing
The temporary object efficiency problem. In terms of language itself, it is sound
C ++
The reference type in is left
Defects in the right value.
From the perspective of database designers,
It brings a powerful tool to database designers.
Slave Database
From the user's point of view, the "free" efficiency can be improved without moving one soldier
...