I tried to teach myself the proper use of move semantics in C ++ 11 through the wonderful C ++ book Bjarne Stroustrup. I ran into a problem - the move constructor is not being called as I expect. Take the following code:
class Test
{
public:
Test() = delete;
Test(const Test& other) = delete;
Test(const int value) : x(value) { std::cout << "x: " << x << " normal constructor" << std::endl; }
Test(Test&& other) { x = other.x; other.x = 0; std::cout << "x: " << x << " move constructor" << std::endl; }
Test& operator+(const Test& other) { x += other.x; return *this; }
Test& operator=(const Test& other) = delete;
Test& operator=(Test&& other) { x = other.x; other.x = 0; std::cout << "x :" << x << " move assignment" << std::endl; return *this; }
int x;
};
Test getTest(const int value)
{
return Test{ value };
}
int main()
{
Test test = getTest(1) + getTest(2) + getTest(3);
}
This code will not compile because I removed the default copy constructor. Adding a default copy constructor, the console output looks like this:
x: 3 normal constructor
x: 2 normal constructor
x: 1 normal constructor
x: 6 copy constructor
However, changing the main function to the following:
int main()
{
Test test = std::move(getTest(1) + getTest(2) + getTest(3));
}
Produces the desired console output:
x: 3 normal constructor
x: 2 normal constructor
x: 1 normal constructor
x: 6 move constructor
, , , (getTest (1) + getTest (2) + getTest (3)) rvalue ( , , test), , , std:: move().
- , ? - ? ?
.
1:
, .
:
friend Test operator+(const Test& a, const Test& b) { Test temp = Test{ a.x }; temp += b; std::cout << a.x << " + " << b.x << std::endl; return temp; }
Test& operator+=(const Test& other) { x += other.x; return *this; }
:
int main()
{
Test test = getTest(1) + getTest(2) + getTest(4) + getTest(8);
}
:
x: 8 normal constructor
x: 4 normal constructor
x: 2 normal constructor
x: 1 normal constructor
x: 1 normal constructor
1 + 2
x: 3 move constructor
x: 3 normal constructor
3 + 4
x: 7 move constructor
x: 7 normal constructor
7 + 8
x: 15 move constructor
, - , , , +, .
, , , , .
2:
. :
friend Test&& operator+(Test&& a, Test&& b) { b.x += a.x; a.x = 0; return std::move(b); }
:
x: 8 normal constructor
x: 4 normal constructor
x: 2 normal constructor
x: 1 normal constructor
x: 15 move constructor
.
3:
, . :
friend Test&& operator+(Test&& a, Test&& b) { b += a; return std::move(b); }
Test& operator+=(const Test& other) { std::cout << x << " += " << other.x << std::endl; x += other.x; return *this; }
:
x: 8 normal constructor
x: 4 normal constructor
x: 2 normal constructor
x: 1 normal constructor
2 += 1
4 += 3
8 += 7
x: 15 move constructor
. rvalue +, +, , + .
, lvalue/rvalue/move semantics.