简体   繁体   中英

why use of deleted rvalue reference constructor function?

This is a very simple example with class A and B. I want allow only deep copy, so I disabled the rvalue reference constructor.

#include <iostream>

class B;

class A {
public:
    A();
    ~A();
    A(const A & other);
    A& operator=(const A & other);
    A(A && ) = delete;
    A& operator=(A && ) = delete;
    B toB() const;

private:
    int a_;
};

class B {
public:
    B();
    ~B();
    B(const B & other);
    B& operator=(const B & other);
    B(B && ) = delete;
    B& operator=(B && ) = delete;
    A toA() const;

private:
    int b_;
};

A::A()
{
}

A::~A()
{
}
A::A(const A & other)
        : a_(other.a_)
{
}
A& A::operator=(const A & other)
{
    a_ = other.a_;
    return *this;
}

B A::toB() const
{
    return B();
}

B::B()
{
}
B::~B()
{
}
B::B(const B & other)
        : b_(other.b_)
{
}
B& B::operator=(const B & other)
{
    b_ = other.b_;
    return *this;
}

A B::toA() const
{
    return A();
}


int main()
{
    A a();
    B b();

    return 0;
}

the gcc compiler report bugs like this:

In member function 'B A::toB() const':
error: use of deleted function 'B::B(B&&)'
     return B();
              ^
note: declared here
     B(B && ) = delete;

I'm wandering why it use B(B && ) function, not the B(const B &) function instead.

Because you added the move-constructor. Deleted but declared functions are still part of the interface of a class. That means it will be considered by the compiler, but since it's marked as deleted you get the error. If you want to force the copy-constructor to be called then remove the move-constructor declaration.


From this deleted functions reference :

Any use of a deleted function is ill-formed (the program will not compile). This includes calls, both explicit (with a function call operator) and implicit (a call to deleted overloaded operator, special member function , ...

[Emphasis mine]

Since the deleted functions are part of the interface, the compiler will try to use them. So when there is a deleted move constructor, the compiler will see that and try to use it, but since it is deleted there will be an error.

Since no move constructor will be created by the compiler if there is an explicit copy constructor (as per this move constructor reference ) simply having a defaulted copy constructor will inhibit moving of object.

All of that means your classes can be very much simplified:

class A {
public:
    A() : a_() {}

    A(const A & other) = default;

    B toB() const;

private:
    int a_;
};

class B {
public:
    B() : b_() {}

    B(const B & other) = default;

    A toA() const;

private:
    int b_;
};

Because the classes above have user-declared copy constructors no movement constructor will be created, and the class can't be moved only copied.

Move Constructor would be called whenever a nameless object is created.

In BA::toB() const function there is a statement return B(); which creates a nameless object to be returned from the function. For creating a nameless object move constructor is required which is deleted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM