urmish
urmish

Reputation: 127

Confusing operation in c++ program while understanding move semantics

I am trying to grasp the concept of move semantics, rvalues, lvalues in c++ and am facing a problem. I am first looking at this popular answer - https://stackoverflow.com/a/3109981/9576161

I wrote a small program based on that reply to understand what is going on. I am using g++ (on linux) and the -fno-elide-constructors for compiling without rvalue optimization by the compiler.

Here is the small program:

#include <iostream>                                                                                                                                                      
#include <cstring>                                                                                                                                                       

using namespace std;                                                                                                                                                     

class string  {                                                                                                                                                          

    public:                                                                                                                                                              
        char* data;                                                                                                                                                      
        string (const char* p) {                                                                                                                                         
            cout << "Constructor 1 called\n";                                                                                                                            
            size_t size = strlen(p) + 1;                                                                                                                                 
            data = new char[size];                                                                                                                                       
            cout << "this location is: " << this << endl;
            memcpy (data,p,size);
        }

        string (string&& that) {
            cout << "Constructor 2 called\n";
            //cout << "data is " << data << " data location is: " << &data << endl;
            cout << "data location is: " << &data << endl;
            cout << "that.data is " << that.data << " that.data location is: " << &that.data << endl;
            data = that.data;
            that.data = nullptr;
            cout << "this location is: " << this << " data is: " << data << endl;
            cout << "data location is: " << &data << endl;
            cout <<  "that.data location is: " << &that.data << endl;
        }

        ~string() {
            delete[] data;
            cout << "Destructor called for object located at: " << this << endl;
        }

        void print() {
            cout << "String is: " << data << endl;
        }
};

int main () {
    ::string R = "12345";
    cout << "R constructed and located at: " << &R << endl << endl;
    return 0;
}

On running the program, I see the following result:

ubuntu@thinkpad:~/programming_practice/c_projects$ g++ -fno-elide-constructors move_semantics_short.cpp 
ubuntu@thinkpad:~/programming_practice/c_projects$ ./a.out 
Constructor 1 called
this location is: 0x7fffac01bb80
Constructor 2 called
data location is: 0x7fffac01bb78
that.data is 12345 that.data location is: 0x7fffac01bb80
this location is: 0x7fffac01bb78 data is: 12345
data location is: 0x7fffac01bb78
that.data location is: 0x7fffac01bb80
Destructor called for object located at: 0x7fffac01bb80
R constructed and located at: 0x7fffac01bb78

Destructor called for object located at: 0x7fffac01bb78
ubuntu@thinkpad:~/programming_practice/c_projects$ 

Notice the line data = that.data in the second constructor (where it says "Constructor 2 is called"). What does it do? Aren't data and that.data both character pointers? Why is data not changing in value? Shouldn't data now equal the value of that.data which is 0x7fffac01bb80? Instead it seems like some kind of memcopy is occurring and the character string that that.data points to is now pointed to by data. Any hints on what is going on would be helpful.

Upvotes: 0

Views: 87

Answers (1)

Miles Budnek
Miles Budnek

Reputation: 30639

The type of &data is char**. That is, it's the memory location of the pointer that stores the memory location of some char.

data = that.data; does not make &data equal &that.data. It just makes data and that.data equal. They now point to the same char, but they each exist independently in memory.

If instead of printing data's address, you print the address stored in data, you can see that you are stealing the array of chars that was owned by that in your move constructor.

Upvotes: 2

Related Questions