просто добавьте деструктор, который ничего не делает, может вызвать ошибку компиляции (вокруг std :: move), почему?

Пока я учился std::moveЯ нашел странную проблему.

Если я добавлю только деструктор, который ничего не делает с идеальной программой, я получу ошибку компиляции.

#include <iostream>
using namespace std;

class M {
public:
int database = 0;

M &operator=(M &&other) {
this->database = other.database;
other.database = 0;
return *this;
}

M(M &&other) { *this = std::move(other); }

M(M &m) = default;
M() = default;
~M() { /* free db */ }
};

class B {
public:
M shouldMove;

//~B(){}   //<---  ## Adding this line will cause compile error. ##
};

int main() {
B b;
B b2 = std::move(b); //## error at this line if the above line is added
return 0;
}

Живой код: https://ideone.com/UTR9ob

Ошибка invalid initialization of non-const reference of type 'B&' from an rvalue of type 'std::remove_reference<B&>::type {aka B}',

Вопрос:

  • (1) Какие правила синтаксиса C ++ обеспечивают это? Другими словами, что означает ошибка?
  • (2) Если я хочу добавить деструктор, который почти ничего не делает (например, только печатает журнал отладки) в BДолжен ли я действительно следовать правило пяти вместо? Если нет, как заставить его скомпилировать? Следование правилу пяти только из-за этого, на мой взгляд, слишком утомительно и грязно.

Я думаю правило нуля это просто хорошая практика.

Однако из этого примера мне кажется, что это жесткое правило, что в случае нарушения я получу ошибку компиляции.

3

Решение

Неявно объявленный конструктор перемещения присутствует, только если класс не имеет объявленного пользователем деструктора. Поэтому ответ на вопрос 2. ДА.

Ответ на 1. состоит в том, что это жесткое правило, и его можно найти в пункте 12.8 стандарта:

Если определение класса X явно не объявляет конструктор перемещения, он будет неявно объявлен
по умолчанию, если и только если

  • X не имеет объявленного пользователем конструктора копирования,
  • X не имеет заявленного пользователем оператора копирования,
  • X не имеет объявленного пользователем оператора назначения перемещения,
  • X не имеет объявленного пользователем деструктора, и
  • конструктор перемещения не будет неявно определен как удаленный.
[Примечание: когда конструктор перемещения не объявлен неявно или не предоставлен явно, выражения, которые
в противном случае вызвал бы конструктор перемещения, может вместо этого вызвать конструктор копирования. — конец примечания]

Лучший способ заставить это работать, это использовать что-то вроде умного указателя, то есть базовый класс или член, который определяет все пять специальных членов (и очень мало других), так что вам не нужно это делать. В этом случае целочисленный дескриптор эквивалентен std::unique_pointer должно хорошо работать. Однако имейте в виду, что базы данных, как и файлы, могут иметь ошибки при закрытии, поэтому стандартная семантика деструктора без выбрасывания не охватывает все случаи.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]