B M
B M

Reputation: 4019

In C++ class with copy & move ctor and copy assignment: no need for move assignment?

If I have a C++ class with copy and move constructors and copy assignment like so:

class Foo {
public:
    int A[];

    // custom ctor
    Foo(size_t N) {
        A = new A[N];
        for(int i = 0; i < N; i++) A[i] = i * i;
    }

    // copy ctor
    Foo(Foo& other) {
        size_t N = sizeof(other.A) / sizeof(int);
        A = new A[N];
        for(int i = 0; i < N; i++) A[i] = other.A[i];
    }

    // move ctor
    Foo(Foo&& other) {
        A = other.A;
        other.A = nullptr;
    }

    // copy assignment AND move assignment?
    Foo& operator=(Foo other) {
        std::swap(this.A, other.A);
        return *this;
    }

    // default dtor
    ~Foo() {
        delete[] A;
    }

Can I in this case simply avoid defining a move assignment operator and assume that still move assignment is taking place when possible? My reasoning behind that is: the copy assignment operator has to construct the Foo object defined as parameter. Now it can choose between the copy ctor and the move ctor as both are available. Thus if given an rvalue it should choose the move ctor and if given an lvalue it should choose the copy ctor. Is this correct?

Also: will this implementation work regarding the sizeof calculation of the array? If not, why not?

Upvotes: 2

Views: 141

Answers (2)

villasv
villasv

Reputation: 6861

You can always don't define the move ctor and assignment operators. All you will lose is opportunity of performance gains. So no, no need for move assignment.

In your case, this example Foo f = Foo(); f = Foo() you're using the normal assignment operator, where you could be doing a move. You will do that in two moves instead plus the swap.

About you sizeof question, it wont work. sizeof will return the size of the pointer type, which is constantEDIT: except for VLA, where it performs a run-time check, so it is correct.

Upvotes: 0

Ben Voigt
Ben Voigt

Reputation: 283971

Recommendation: Use std::vector

Problem: int A[]; is a flexible array member, which gets its storage from extra memory adjacent to the main object. You can't do A = new int[N]; nor sizeof (A).

Fix: You can use int* A; and keep track of the size yourself, because sizeof a pointer isn't related to the size of the array it points to.

Better: std::vector<int> remembers its size and implements destructor, move, and copy operations so you don't have to.


Regarding the question about implementing assignment using pass-by-value: Yes, that's legal, it's even an idiom: "copy-and-swap". However, it will cause an unnecessary extra move in the move assignment case, so you may want to implement that directly. Or not, since two moves should barely cost more than the required one.

If you use std::vector to store your data, the compiler-generated copy and move operations will do the right thing automatically.

Upvotes: 3

Related Questions