asimes
asimes

Reputation: 5894

Usages of std::move

Below in the question is a simplified version of code for SO. The original code:

The simplified code for SO doesn't have the original structure, I just made up data with loops. However the detail which is still important is that the new structure's constructor will be passed std::vector. Those are populated in the loops and moved to the new structure

It occurred to me that the std::vector will not be needed after the new structure is made so std::move would be appropriate. I have labeled the usages as "Move 1", "Move 2", "Move 3", and "Move 4" in the code below:

#include <iostream>
#include <vector>

struct A {
    const int m_a;

    A() = delete;
    A(const int a_a) : m_a(a_a) {}

    void display() const { std::cout << "    " << m_a << "\n"; }
};

struct B {
    const std::vector<A> m_as;
    const int            m_b;

    B() = delete;
    B(
        std::vector<A>&& a_as,
        const int        a_b
    ) :
        m_as(std::move(a_as)), // Move 1
        m_b(a_b)
    {}

    void display() const {
        std::cout << "  " << m_b << ":\n";
        for (const A& a : m_as)
            a.display();
    }
};

struct C {
    const std::vector<B> m_bs1;
    const std::vector<B> m_bs2;

    C() = delete;
    C(
        std::vector<B>&& a_bs1,
        std::vector<B>&& a_bs2
    ) :
        m_bs1(std::move(a_bs1)), // Move 2
        m_bs2(std::move(a_bs2))  // Move 2
    {}

    void display() const {
        std::cout << "0:\n";
        for (const B& b : m_bs1)
            b.display();
        std::cout << "1:\n";
        for (const B& b : m_bs2)
            b.display();
    }
};

int main() {
    // Manually making up data, actual usage will take data from a different
    // kind of structure and populate vectors
    std::vector<B> bs1, bs2;
    for (int i = 0; i < 3; ++i) {
        std::vector<A> as;
        for (int j = 0; j < 2; ++j)
            as.emplace_back(j);
        bs1.emplace_back(std::move(as), i); // Move 3
    }
    for (int i = 0; i < 3; ++i) {
        std::vector<A> as;
        for (int j = 0; j < 2; ++j)
            as.emplace_back(j);
        bs2.emplace_back(std::move(as), i); // Move 3
    }

    C c(std::move(bs1), std::move(bs2)); // Move 4
    c.display();
    return 0;
}

Some assumptions:

The question: Are all of the std::move usages meaningful or are any of them unnecessary?

Upvotes: 3

Views: 278

Answers (1)

Alan Birtles
Alan Birtles

Reputation: 36379

You can see most of the std::moves are required by removing them, your code wont compile. The only exceptions are Move 1 and Move 2, the code will still compile without them but only because the std::vector copy constructor is invoked instead.

If you want to move from an object you almost always need to use std::move, the only exceptions are when moving from a temporary and when returning an object.

Upvotes: 4

Related Questions