Почему конструктор копирования вызывается вместо конструктора перемещения в моем коде? - PullRequest
2 голосов
/ 26 сентября 2019

Я пытаюсь понять конструктор перемещения и ссылку на значение.Поэтому я попробовал этот код на https://www.onlinegdb.com/online_c++_compiler. Но результат меня смущает.

#include <iostream>
#include <type_traits>


class A {
public:
  A() { std::cout << "Constructed" << std::endl; }
  A(const A& )= delete;
  A(A&&) { std::cout << "Move Constructed" << std::endl; }
};

int
main ()
{
  A&& a = A();
  A b = a; // error: use of deleted function ‘A::A(const A&)’
  //A b = static_cast<decltype(a)>(a); // This works, WTF?
  std::cout << std::is_rvalue_reference<decltype(a)>::value << std::endl; // pretty sure a is rvalue reference.

  return 0;
}

Ответы [ 2 ]

5 голосов
/ 26 сентября 2019

Вы путаете с типами и значениями категорий .

(выделено мной)

Каждое выражение C ++ (оператор с его операндами, литералом, именем переменной и т. Д.) Характеризуется двумя независимыми свойствами: тип и категория значения .

В качестве именованной переменной a является lvalue.

Следующие выражения lvalue-выражения :

  • имя переменной, ...
  • ...

Затем для A b = a; выбирается конструктор копирования.Как вы уже пытались, static_cast<decltype(a)>(a); преобразует его в xvalue (что является rvalue);Вы также можете использовать std::move.

A b = std::move(a);

Следующие выражения xvalue выражений :

  • вызов функции или перегруженное выражение оператора, типом возвращаемого значения которого является rvalue ссылка на объект, например std::move(x);
  • ...
1 голос
/ 26 сентября 2019
A&& a = A();

не дает вам значения.Один из способов восприятия любого значения как значения rvalue состоит в том, что вы не можете получить его адрес.Если вы можете получить его адрес, то это скорее всего lvalue.Итак, в вашем случае

auto address_of_a = &a;

возможно (так, a является lvalue).

decltype(a)

является A && (тип rvalue).поэтому приведение типа к A && даст вам rvalue

A b = a;

, потому что a - lvalue, поэтому он ищет A (const A &).

A b = std::move(a); // or
A b = A{}; // rvalue

будет успешным, поскольку теперь он будет искать A (A &&)

A b;
A c = A{};
b = std::move(c);

не удастся, если вы определите свое перемещение как удаленное, в то время как

b = c;

будет успешным, если вы определите свое назначение копирования.

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

...