Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++11 Why doesn't this move constructor work?

Tags:

c++11

move

I've written the code posted below. I was hoping to get to move the content of a vector between instances of LargeClass. The move constructor is being used, but instead of moving I get copies only.

Why doesn't the move semantics work as expected here?

Code:

#include <iostream>
#include <vector>

class LargeClass
{
public:
    explicit LargeClass (void): numbers(20, 10) 
    {
    }
    LargeClass (const LargeClass &rhs): numbers(rhs.numbers)
    { 
        std::cout << "Using LargeClass copy constructor" << '\n';
    }
    LargeClass (const LargeClass &&rhs): numbers(std::move(rhs.numbers))
    { 
        std::cout << "Using LargeClass move constructor" << '\n';
    }

    const int* getNumbersAddress(void) const
    {
        return (numbers.data());
    }

private:
    std::vector<int> numbers;
};

int main()
{
    LargeClass l1;
    std::cout << "l1 vector address: " << l1.getNumbersAddress() << '\n';

    LargeClass l2(l1);
    std::cout << "l1 vector address: " << l1.getNumbersAddress() << '\n';
    std::cout << "l2 vector address: " << l2.getNumbersAddress() << '\n';

    LargeClass l3 = std::move(l2); 
    std::cout << "l1 vector address: " << l1.getNumbersAddress() << '\n';
    std::cout << "l2 vector address: " << l2.getNumbersAddress() << '\n';
    std::cout << "l3 vector address: " << l3.getNumbersAddress() << '\n';

    return 0;
}

Possible output:

l1 vector address: 0x18ce010
Using LargeClass copy constructor
l1 vector address: 0x18ce010
l2 vector address: 0x18ce070
Using LargeClass move constructor
l1 vector address: 0x18ce010
l2 vector address: 0x18ce070
l3 vector address: 0x18ce0d0
like image 225
Sebastian Kramer Avatar asked Jun 02 '26 18:06

Sebastian Kramer


2 Answers

The rvalue references don't make sense in their const forms because you want to modify them (you want to "move" them ). Objects created as const in C++ are in read-only memory, from which grabbing/modifying internal resources won't be possible.

The syntax for move constructor normally should be

  • class_name ( class_name && )

So use :

LargeClass ( LargeClass&& rhs )

like image 67
P0W Avatar answered Jun 06 '26 06:06

P0W


Although a constructor taking const LargeClass&& is technically known as a move constructor (12.8/3) (which is baffling, but explicitly stated in [C++11: 12.8/3]), it's pretty bloomin' useless; it's self-evident that you cannot move from a const expression, because you cannot modify const things and moving implies altering the source! In particular, you cannot actually move from a const vector, which is why that does not occur here and why you see what you see.

A more useful move constructor looks like this:

LargeClass(LargeClass&& rhs)
like image 23
Lightness Races in Orbit Avatar answered Jun 06 '26 05:06

Lightness Races in Orbit



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!