Search code examples
c++c++11movemove-semanticsmove-constructor

Despite passing an rvalue, why isn't my move constructor getting called?


I create a class string by defining default, copy & move constructor. I try to create objects expecting each constructor to be invoked. As expected, the default & copy constructor are invoked, but when I pass a rvalue(temporary object), I still see move constructor NOT being invoked.

#include <iostream>
#include <cstdlib>
#include <cstring>

class string
{
    char * data;
public:
    string(const char * p = nullptr)
    {
        if(p == nullptr) return;
        std::cout << "string(const char * p)" << std::endl;
        size_t size = strlen(p) + 1;
        data = new char[size];
        memcpy(data, p, size);
    }
    ~string()
    {
        std::cout << "~string() - " << data << std::endl;
        delete[] data;
    }
    string(const string & that)
    {
        std::cout << "string(const string &)" << std::endl;
        size_t size = strlen(that.data) + 1;
        data = new char[size];
        memcpy(data, that.data, size);
    }
    string(string && that)
    {
        std::cout << "string(string && )" << std::endl;
        data = that.data;
        that.data = nullptr;
    }
    void showData() { std::cout << data << std::endl; }
    string operator+(const string & other)
    {
        size_t datasize = strlen(data);
        size_t othersize = strlen(other.data);
        size_t totalsize = datasize + othersize + 1;
        char * sData = new char[totalsize];
        memcpy(sData, data, strlen(data));
        memcpy(sData+datasize, other.data, totalsize-datasize);
        string s(sData);
        delete[] sData;
        return s;

    }
    string & operator=(string that)
    {
        char * tmp = data;
        data = that.data;
        that.data = tmp;
        return *this;
    }
};

int main()
{
    string s1{"stackoverflow"};  // s1
    string s2{s1};               // s2
    string s3{string("stack")+string("exchange")};  // s3
}

At s1: default constructor is being called as expected.

At s2: copy constructor is invoked, also as expected.

At s3: I'm passing a temporary object. So, I expect move constructor be invoked, but default constructor being called.

I'm unable to comprehend what I'm missing. Kindly help, thanks.


Solution

  • Indeed it behaves as you say with GCC and Clang, but the move constructor is called with VC++. Looks like a bug, then you should move explicitly with std::move().