C ++ 11 Moving Semantics

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.

+3
1

getTest(1) + getTest(2) + getTest(3) , Test::operator+(const Test&). Test& , , lvalue.

operator + - , :

Test operator + (const Test& a, const Test& b)

Test operator + (Test a, const Test& b)

operator += operator+.

+3

All Articles