I read a Microsoft tutorial (located here: https://learn.microsoft.com/en-us/cpp/cpp/move-constructors-and-move-assignment-operators-cpp?view=msvc-170) about the move constructor and the move assignment operator and I didn't quite understand when the move ctor is invoked.
Below the code of the MemoryBlock class
class MemoryBlock
{
public:
    explicit MemoryBlock(size_t length)
        : m_length(length),
          m_data(new int[length])
    {
        std::cout << "In MemoryBlock(size_t). length = "
                  << m_length << "." << std::endl;
    }
    virtual ~MemoryBlock()
    {
        std::cout << "In ~MemoryBlock(). length = "
                  << m_length << ".";
        if (m_data != nullptr)
        {
            delete[] m_data;
            m_data = nullptr;
        }
        std::cout << std::endl;
    }
    // Copy ctor
    MemoryBlock(const MemoryBlock& other)
        : m_length(other.m_length),
          m_data(new int[other.m_length])
    {
        std::cout << "In MemoryBlock(const MemoryBlock&). length = "
                        << other.m_length << ". Copying resource." << std::endl;
        std::copy(other.m_data, other.m_data + m_length, m_data);
    }
    // Copy assignment operator
    MemoryBlock& operator=(const MemoryBlock& other)
    {
        std::cout << "In operator=(const MemoryBlock&). length = "
                        << other.m_length << ". Copying resource." << std::endl;
        if (this != &other)
        {
            delete[] m_data;
            m_length = other.m_length;
            m_data = new int[m_length];
            std::copy(other.m_data, other.m_data + m_length, m_data);
        }
        return *this;
    }
    // Move ctor
    MemoryBlock(MemoryBlock&& other) noexcept
        : m_length(0),
          m_data(nullptr)
    {
        std::cout << "In MemoryBlock(MemoryBlock&&). length = "
                     << other.m_length << ". Moving resource." << std::endl;
        m_data = other.m_data;
        m_length = other.m_length;
        other.m_data = nullptr;
        other.m_length = 0;
    }
    // Move assignment
    MemoryBlock& operator=(MemoryBlock&& other) noexcept
    {
        // Avoid assigning the object to itself
        if (this != &other)
        {
            // Free the existing resource
            delete[] m_data;
            m_data = other.m_data;
            m_length = other.m_length;
            other.m_data = nullptr;
            other.m_length = 0;
        }
        return *this;
    }
private:
    size_t m_length;
    int *m_data;
};
What I don't I understand is in the main. Understand why the move ctor is invoked rather than the copy ctor
int main()
{
    std::vector<MemoryBlock> v;
    // In this way the copy ctor is called
    MemoryBlock m(10);
    v.push_back(m);
    // And in this way the move ctor is called, why if std::move is not invoked?
    v.push_back(MemoryBlock(25));
    return 0;
}
I compiled and built the code and tried to understand, also searching for information in internet without any result
 
     
     
     
    