Страницы

Поиск по вопросам

вторник, 2 октября 2018 г.

Чем пустой конструктор по умолчанию отличается от =default;?

Для конструктора по умолчанию, чем пустое тело отличается от того что получается с =default?
X::X() {} // и X::X() = default;


Ответ

Наличие конструктора по умолчанию с пустым телом автоматически делает класс нетривиальным. Со всеми вытекающими отсюда особенностями. Например делает тип не POD. А также исключает возможность использовать агрегатную инициализацию:
#include #include
struct X { //X() {} X() = default; int a; int b; };
int main( ) { X x { 1, 2 }; // ошибка, если X - не тривиальный класс. std::cout << std::boolalpha << std::is_trivial::value << "
"; }
При определении конструктора как = default тривиальность класса сохраняется, если она была до этого. В данном случае, это равносильно отсутствию явного упоминания конструктора в определении класса.
Если конструктор по умолчанию определен как = default вне определения класса, всё равно будет считаться, что конструктор предоставлен пользователем, и это тоже делает класс нетривиальным
Сноска на Стандарт по этому поводу (8.4.2/5):
A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.

Различие также будет наблюдаться при попытке создания константного объекта класса конструктором по умолчанию. Например:
const X x;
приведет к ошибке компиляции при определении класса X как:
struct X { X() = default; int i; };
И скомпилируется удачно в случае предоставленного пользователем конструктора по умолчанию:
struct X { X() {} int i; };

Еще один момент, демонстрирующий различие, возникает при использовании пустого списка инициализации при определении объекта. Например:
X x = { };
приведёт к обнулению всех членов класса при = default или отсутствующем явно конструкторе. Если же конструктор будет определён с пустым телом, то такая запись оставит члены класса неинициализированными (мусор).

Комментариев нет:

Отправить комментарий