Что такое нетривиальный конструктор в С++?

Я читал этот http://en.wikipedia.org/wiki/C%2B%2B0x#Modification_to_the_definition_of_plain_old_data

В нем упоминается тривиальный конструктор по умолчанию, тривиальный конструктор копирования, оператор присваивания копий, тривиальный деструктор. Что тривиально, а не тривиально?

Ответ 1

Простыми словами "тривиальная" специальная функция-член буквально означает функцию-член, которая делает свою работу очень простым способом. "Прямой способ" означает различную вещь для различных видов специальных функций-членов.

Для конструктора по умолчанию и деструктора, который является "тривиальным", означает буквально "ничего не делать". Для оператора copy-constructor и copy-assign оператор "тривиальный" означает буквально "эквивалентен простому необработанному копированию памяти" (например, копия с memcpy).

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

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

Например, если класс имеет виртуальные функции, для создания объектов этого класса потребуются дополнительные скрытые инициализации (инициализировать таблицу виртуальных методов и т.д.), поэтому конструктор для этого класса не будет считаться тривиальным.

В другом примере, если класс имеет виртуальные базовые классы, каждый объект этого класса может содержать скрытые указатели, указывающие на другие части одного и того же объекта. Такой самореферентный объект не может быть скопирован простой процедурой копирования необработанной памяти (например, memcpy). Дополнительные манипуляции будут необходимы для правильной повторной инициализации скрытых указателей в копии. По этой причине конструктор копирования и оператор присваивания копии для этого класса не будут считаться тривиальными.

По понятным причинам это требование рекурсивно: все подобъекты класса (базы и нестатические члены) также должны иметь тривиальные конструкторы.

Ответ 2

Конструктор класса A тривиальный, если все верно:

  • Он неявно определен (синтезирован компилятор)
  • A не имеет виртуальных функций и виртуальных базовых классов
  • Все прямые базовые классы A имеют тривиальные конструкторы
  • Классы всех нестатических элементов данных A имеют тривиальные конструкторы

Ответ 3

Есть правильные ответы уже, но вот цитата из Стандарта (которую я искал, когда я наткнулся на это сообщение):

(§12.1/5) Конструктор по умолчанию является тривиальным, если он не предоставляется пользователем, и если:
- его класс не имеет виртуальных функций (10.3) и не имеет виртуальных базовых классов (10.1) и - элемент нестатического данных его класса не имеет элементарного или равного-инициализатора, и - все прямые базовые классы его класса имеют тривиальные конструкторы по умолчанию и
- для всех нестатических членов данных своего класса, которые относятся к типу класса (или его массиву), каждый такой класс имеет тривиальный конструктор по умолчанию.

Это из С++ 11. В С++ 03 отсутствует второй элемент и используется фраза, неявно объявленная, а не предоставляемая пользователем. Это в противном случае идентично.

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