Почему неявно сгенерированный конструктор (и др.) Был бы более эффективным, чем определяемый пользователем (тривиальный)? - PullRequest
11 голосов
/ 25 ноября 2010

Я прочитал эту статью от Д. Калева этим утром о новой функции c ++ 11 "функции по умолчанию и удаленные функции", и не могу понять часть о производительности, а именно:

ручное определение специальной функции-члена (даже если она тривиальная) обычно менее эффективно, чем неявно определенная.

Погуглив, чтобы найти ответ, я нашел еще одну статью того же автора:

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

Объяснения нет, но я время от времени читаю подобные заявления.

Но как это так:

class C { C() = default; };

может быть более эффективным, чем

class C { C(){} };

? Я думаю, что компилятор был бы достаточно умен, чтобы обнаружить такую ​​ситуацию и оптимизировать ее. Другими словами, как компилятору легче оптимизировать, когда он видит =default вместо {} (функция void body)?

Редактировать: вопрос был отредактирован для добавления тега "c ++ 11", но этот вопрос остается в контексте c ++ 03: просто замените class C {C()=default;}; на class C {};, так что на самом деле не относится к конкретному c ++ 11 вопрос.

Ответы [ 4 ]

7 голосов
/ 25 ноября 2010

Вы спрашиваете, как получается, что

class C { C() = default; };

может быть более эффективным, чем

class C { C(){} };

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

Но в более общем смысле, например, как конструктор копирования, можно представить, что копирование одного элемента POD за один раз не будет признано оптимизируемым простым оптимизатором, тогда как при автоматической генерации это может просто сделать memcpy. Кто знает. Это проблема качества реализации, и я легко могу представить себе также напротив .

Итак, измерьте, если это имеет значение.

Приветствия & hth.,

4 голосов
/ 11 декабря 2010

Нет никакого смысла говорить о «ручном определении специальной функции-члена (даже если она тривиальная)», потому что предоставляемые пользователем специальные функции-члены, по определению, нетривиальны. Эта нетривиальность вступает в игру при использовании признаков типа, а также POD-ness, и многие оптимизации возможны только для тривиальных или POD-типов.

Лучшее подтверждение той же цитаты будет:

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

Из раздела 12.1 [class.ctor]

Конструктор по умолчанию - Тривиальный , если он не предоставляется и не удаляется пользователем и если:

  • его класс не имеет виртуальных функции (10.3) и нет виртуальной базы классы (10,1) и
  • нет нестатических член данных своего класса имеет инициализатор скобки или равнозначный, и
  • все прямые базовые классы своего класса иметь тривиальные конструкторы по умолчанию и
  • для всех нестатических элементов данных своего класса, которые имеют тип класса (или их массив), каждый такой класс имеет тривиальный конструктор по умолчанию.

В противном случае конструктор по умолчанию нетривиальным .

Из раздела 12.8 [class.copy]:

Конструктор копирования / перемещения для класса X тривиальный , если он не предоставлен пользователем ни удалено, и если

  • класс X не имеет виртуальные функции (10,3) и нет виртуальные базовые классы (10.1) и
  • конструктор, выбранный для копирования / перемещения каждый подобъект прямого базового класса тривиальный и
  • для каждого нестатического член данных X, который имеет тип класса (или его массив), конструктор выбран для копирования / перемещения этого члена тривиальный;

в противном случае копирование / перемещение конструктор нетривиален .

Из раздела 9, [class]:

A тривиально копируемый класс - это класс что:

  • не имеет нетривиальной копии конструкторы (12,8),
  • не имеет нетривиальные конструкторы перемещения (12,8),
  • не имеет нетривиального назначения копирования операторы (13.5.3, 12.8),
  • не имеет нетривиальные операторы назначения перемещения (13.5.3, 12.8) и
  • имеет тривиальное деструктор (12,4).

A тривиальный класс - класс, который имеет тривиальный конструктор по умолчанию (12.1) и является тривиально копируемым. [Примечание: в в частности, тривиально копируемый или тривиальный класс не имеет виртуального функции или виртуальные базовые классы. - конечная нота]

2 голосов
/ 25 ноября 2010

Принимайте претензии к производительности "с крошкой соли".

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

Такие конструкторы и деструкторы могут иметь и другие преимущества, но заявления о производительности (за исключением big-O) редко бывают даже значимыми, за исключением весьма надуманных обстоятельств.

0 голосов
/ 25 ноября 2010

Если честно, я тоже этого не вижу.

Помимо всего прочего, я понимаю, почему следует использовать

class C { C() = default; };

, который мне кажется таким же, как

class C { };

Или, если предусмотрены другие конструкторы, как:

class C { 
    C() {}
    // other constructors.
};

Я не вижу реальной проблемы , о которой пишет автор.

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