JerryThePineapple
JerryThePineapple

Reputation: 71

c++ move semantics does not perform move

Idea is to use move semantics to avoid unnecessary copying. Given the code below:

#include <iostream>
#include <string>
#include <utility>



class Address {
private:
    const std::string m_street;
    const std::string m_city;
    const int m_suite;

public:
    Address(const std::string &street, const std::string &city, int suite) : m_street {std::move(street)},
                                                                            m_city {std::move(city)},
                                                                            m_suite {suite}
    {
    }

    friend std::ostream& operator<<(std::ostream &out, const Address &address)
    {
        out << "Address: (street: " << address.m_street << ", city: " << address.m_city << ", suite: " << address.m_suite << ")\n";

        return out;
    }

    Address(const Address &other) = delete;

    Address& operator=(const Address &other) = delete;

    Address(Address &&other) : m_street {std::move(other.m_street)},
                               m_city {std::move(other.m_city)},
                               m_suite {std::move(other.m_suite)}
    {
    }
};


class Contact {
    const std::string m_name;
    const Address m_address;

public:
    Contact(const std::string &name, Address &address) : m_name {std::move(name)},
                                                        m_address {std::move(address)}
    {
    }

    friend std::ostream& operator<<(std::ostream& out, const Contact &contact)
    {
        out << "Contact: " << contact.m_name << "\n" << contact.m_address << "\n";

        return out;
    }
};


int main()
{
    Address address1 {"123 East Dr", "London", 123};
    Contact john {"John Doe", address1};

    std::cout << john;
    std::cout << address1;

    return 0;
}

I get the prinout of:

Contact: John Doe
Address: (street: 123 East Dr, city: London, suite: 123)

Address: (street: 123 East Dr, city: London, suite: 123)

Why isn't the content of the address1 variable moved? Shouldn't the printout be

Address: (street: , city: , suite: <whatever>)

Also, why is there a restriction for a post that is mostly code? Everything is given in the code. I was interested in move semantics so I created address1 variable that will hold some address. I used the same variable to initialize an object of type Contact (using the move semantics), but the move semantics is not performed and the address1 variable still holds the same values.

Upvotes: 1

Views: 231

Answers (1)

songyuanyao
songyuanyao

Reputation: 172884

The data member m_street and m_city are declared as const; then in the member initializer list of move constructor of Address like m_street {std::move(other.m_street)}, the copy constructor (but not move constructor) of std::string is used.

You might want to remove the const qualifier, then you'll get

Contact: John Doe
Address: (street: 123 East Dr, city: London, suite: 123)

Address: (street: , city: , suite: 123)

LIVE

BTW: For built-in types like int, the effect of move is same as copy. That's why the value of suite is still 123.

BTW2: For the move constructor of std::string,

Move constructor. Constructs the string with the contents of other using move semantics. other is left in valid, but unspecified state.

After move operation the moved object doesn't guarantee to be modified to empty.

Upvotes: 4

Related Questions