Когда присутствуют оба механизма перемещения и копирования, какой из них будет вызываться?

Ниже представлен класс A, полный конструктора разных типов. Если я комментирую конструктор перемещения, то конструктор копирования вызывается дважды: один раз для передачи объекта функции fun по значению и другим путем возврата из той же функции.

Фрагмент кода

класс A {

int x;

public :
A() {
    cout<<"Default Constructor\n";
}

A(A&& a) : x(a.x){
    cout<<"Move Constructor\n";
    a.x=0;
}

A(const A& a){
    x=a.x;
    cout<<"Copy Constructor\n";
}

A fun(A a){
    return a;
}

};

int main() {

A a;
A b;
A c;
c=a.fun(b);

}

OUTPUT:

Default Constructor

Default Constructor

Default Constructor

Copy Constructor

Move Constructor

Однако, если присутствует конструктор перемещения, он вызывается вместо конструктора копирования. Может ли кто-нибудь сформулировать это с хорошим примером, так что я буду ясно понимать эту концепцию.

Буду признателен за вашу помощь. Спасибо.

Ответ 1

Стандарт допускает специальный случай для случая, когда выражение в выражении return является автоматической переменной продолжительности. В этом случае перегрузки конструктора выбираются так, как если бы выражение в return было rvalue.

Чтобы быть более точным, если выражение в выражении return было автоматической переменной продолжительности, которая имела право на копирование, или если вы проигнорировали факт, что это аргумент функции, тогда требуется компилятор рассматривать его как rvalue с целью разрешения перегрузки. Обратите внимание, что в С++ 11 выражение оператора return должно иметь тип cv-unqualified в качестве возвращаемого типа функций. Это немного смягчилось в С++ 14.

Например, в С++ 11 следующий код вызывает конструктор копирования A вместо конструктора перемещения:

class A
{
};

class B
{
public:
B(A a) : a(std::move(a)){}
A a;
};

B f(A a)
{
return a;///When this is implicitly converted to `B` by calling the constructor `B(a)`, the copy constructor will be invoked in C++11. This behaviour has been fixed in C++14.
}

Ответ 2

в функции A fun (A a) переданная в "копии" A в основном временная переменная. Если конструктор перемещения отсутствует, возвращаемое значение является копией (т.е. Конструктором копирования).

Если есть конструктор перемещения, тогда компилятор может выполнять более эффективную "движущуюся" систематику на временную переменную "A a".