Как правильно вызывать конструкторы перемещения в производном классе? - PullRequest
1 голос
/ 28 сентября 2019

Я пишу фрагмент кода, который наследуется от предоставленного пользователем класса (не по причинам полиморфизма).Мне нужно написать явный конструктор / назначение перемещения для него, потому что я храню указатели на некоторые внутренние данные моего класса.Я не знаю, как правильно вызвать конструктор перемещения.

Пример:

template <typename UserType>
class my_class : UserType  {
  other_data data;
 public:
  my_class(my_class&& x) UserType(/*...*/), data(std::move(x.data)) {}
};

Параметры:

  • Я могу позвонить move(x) => но тогдаэто использование после хода.
  • Я могу сделать немного static_cast<UserType&&>(x) - но это довольно необычно.

Какое здесь хорошее решение?

Ответы [ 2 ]

2 голосов
/ 28 сентября 2019

Как вы, скорее всего, уже знаете, std::move равно вашему static_cast.Следовательно, технически нет никакой разницы.

Поскольку базовый конструктор перемещения знает только ваш базовый класс, доступ к вашим собственным членам будет безопасным.Я полагаю, что лучшее решение здесь - просто использовать = default; и убедиться, что все специальное поведение помещается в отдельный класс, который не должен иметь дело с нужным вам специальным поведением.

0 голосов
/ 30 сентября 2019

Вызов move(x) - самый канонический способ: конструктор базовых перемещений никогда не будет путаться с производными членами класса, не вызывая неопределенное поведение.

Обратите внимание, что «использование после перемещения» обычно допустимо, стандарт c ++ требует, чтобы «Если не указано иное, все объекты стандартной библиотеки, из которых были перемещены, помещались в допустимое, но неопределенное состояние».Это означает, что их функции-члены по-прежнему могут вызываться, если они не требуют предварительных условий.Рассмотрим пример:

vector<int> a = { 1, 2, 3 };
vector<int> b(std::move(a));
//std::cout << a.back();  <- Invalid call. We don't know whether a is empty.
a.clear();   // Ok. clear() doesn't require preconditions.
a.push_back(0);   //Ok. Now a is { 0 }

Кроме того, для вызова деструктора обычно требуется действительность объекта (чего нельзя избежать, если объект имеет длительность автоматического хранения).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...