Semantics of Force Move

I am trying to use move semantics (just like an experiment). Here is my code:

class MyClass {
public:
    MyClass(size_t c): count(c) {
        data = new int[count];
    }



    MyClass( MyClass&& src) : count(src.count) {
        data = src.data;
        src.count = 0;
        src.data = nullptr;
    }

    void operator=( MyClass&& src) {
        data = src.data;
        count = src.count;
        src.count = 0;
        src.data = nullptr;
    }




    ~MyClass() {
        if (data != nullptr)
            delete[] data;
    }

    int* get_data() const {
        return data;
    }

    size_t get_count() const {
        return count;
    }

private:

    MyClass(const MyClass& src) : count(src.count) {
        data = new int[src.count];
        memcpy(data, src.data, sizeof(int)*src.count);
    }

    void operator=(const MyClass& src) {
        count = src.count;
        data = new int[src.count];
        memcpy(data, src.data, sizeof(int)*src.count);
    }


    int* data;
    size_t count;
};


int main()
{
    MyClass mc(150);
    for (size_t i = 0; i < mc.get_count(); ++i)
        mc.get_data()[i] = i;
    MyClass &&mc2 = std::move(mc);

    return 0;
}

But std :: move does not move mc to mc2, it just copies (copy index as it is). If I remove the instance constructor compiler, it will create it for MyClass.

How can I force the use of semantics of movement? How can I use it in such constructions:

MyClass mc2(mc); //Move, not copy
-or-
MyClass mc2 = mc; //Move, not copy

I tried using the '& &' operator to explicitly label the rvalue, but, due to the reason, this did not work.

+3
source share
3 answers

You declare m2as a reference, not as a value. Therefore, it still refers to what was initialized, namely m1. You wanted this:

MyClass mc2 = std::move(mc);

Living example

- ​​:

MyClass mc2(mc); //Move, not copy
//-or-
MyClass mc2 = mc; //Move, not copy

. lvalue ( mc lvalue), std::move ( cast to rvalue).

, , , . ( ) , . - std::auto_ptr , . , , . , std::move.


:

  • delete delete[] no-op, if .

  • std::copy memcpy ++, , sizeof

+2

. , , . :

  • MyClass(size_t c) c != 0.
  • in void operator=(const MyClass& src) not delete[] data; ( ) .

. , .

class MyClass {
private:
    // initialize memebers directly
    int* data = nullptr;
    size_t count = 0;
public:
    // default empty contructor
    MyClass() = default;
    // destructor
    ~MyClass() {
        *this = nullptr; // use operator = (nullptr_t)
    }
    // allow nullptr construct
    MyClass(nullptr_t):MyClass() {}
    // allow nullptr assignment (for clearing)
    MyClass& operator = (nullptr_t) {
        if(data) {
            delete[] data;
            data = nullptr;
        }
        count = 0;
        return *this;
    }
    // chain to default constructor, redundant in this case
    MyClass(size_t c):MyClass() {
        // maybe size_t is 0?
        if(count = c) {
            data = new int[count];
        }
    }
    // chain to default constructor, redundant in this case
    MyClass(MyClass&& src):MyClass() {
        *this = std::move(src); // forward to move assignment
    }
    MyClass& operator=(MyClass&& src) {
        // don't swap with self
        if(&src != this) {
            // it better to swap and let src destroy when it feels like it.
            // I always write move contructor and assignment to swap data.
            // it gonna be destroyed anyway, or not...
            std::swap(src.data, data);
            std::swap(src.count, count);
        }
        return *this;
    }
    MyClass(const MyClass& src):MyClass() {
        *this = src; // forward to copy assignment
    }
    MyClass& operator = (const MyClass& src) {
        // don't copy to self
        if(&src != this) {
            // delete first
            if(data) {
                delete[] data;
                data = nullptr;
            }

            // now reallocate
            if(count = src.count) {
                data = new int[count];
                memcpy(data, src.data, sizeof(int)* count);
            }
        }
        return *this;
    }
    // easy way to use the object in a if(object) to test if it has content
    explicit operator bool() const {
        return data && count;
    }
    // same as above but made for if(!object) to test if empty
    bool operator !() const {
        return !data || !count;
    }
public:
    int* get_data() const {
        return data;
    }
    size_t get_count() const {
        return count;
    }
    // add more custom methods
};

:

MyClass object1; // default construct
MyClass object1(5); // construct with capacity
MyClass object2(object1); // copy constructor
MyClass object3(std::move(object1)); // move constructor
object2 = object1; // copy assignment
object3 = std::move(object1); // move constructor
std::swap(object2, object3); // swap the two
object2 = nullptr; // to empty it
if(object1); // bool cast
0

,

MyClass(const MyClass& src)= delete;
void operator=(const MyClass& src) = delete;

.

0

All Articles