Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the use of std::move have any performance benefits?

Please consider this code :

#include <iostream>
#include <vector>
#include <utility>

std::vector<int> vecTest;
int main() 
{
    int someRval = 3;
    vecTest.push_back(someRval);
    vecTest.push_back(std::move(someRval));
    return 0;
}

So as far as I understand, someRval's value will be copied into vecTest on the first call of push_back(), but on the second someRval produces an x value. My question is, will there ever be any performance benefit, I mean probably not with int but would there maybe be some performance benefit when working with much larger objects?

like image 709
Geoff Avatar asked Dec 19 '22 12:12

Geoff


1 Answers

The performance benefit from moving usually comes from dynamic allocation being ruled out.

Consider an over-simplified (and naive) string (missing a copy-assignment operator and a move-assignment operator):

class MyString
{
public:
    MyString() : data(nullptr) {}

    ~MyString()
    {
        delete[] data;
    }

    MyString(const MyString& other) //copy constructor
    { 
        data = new char[strlen(other.c_str()) + 1]; // another allocation
        strcpy(data, other.c_str()); // copy over the old string buffer
    }

    void set(const char* str)
    {
        char* newString = new char[strlen(str) + 1];
        strcpy(newString, str);
        delete[] data;
        data = newString;
    }

    const char* c_str() const
    {
        return data;
    }
private:
    char* data;
};

This is all fine and dandy but the copy constructor here is possibly expensive if your string becomes long. The copy constructor is however required to copy over everything because it's not allowed to touch the other object, it must do exactly what it's name says, copy contents. Now this is the price you have to pay if you need a copy of the string, but if you just want to use the string's state and don't care about what happens with it afterwards you might as well move it.

Moving it only requires to leave the other object in some valid state so we can use everything in other which is exactly what we want. Now, all we have to do instead of copying the content our data pointer is pointing to is just to re-assign our data pointer to the one of other, we're basically stealing the contents of other, we'll also be nice and set the original data pointer to nullptr:

MyString(MyString&& other)
{
    data = other.data;
    other.data = nullptr;
}

There, this is all we have to do. This is obviously way faster than copying the whole buffer over like the copy constructor is doing.

Example.

like image 77
Hatted Rooster Avatar answered Dec 21 '22 02:12

Hatted Rooster