Какова производительность при конвертации в bool на С++?

[Этот вопрос связан, но не совпадает с этим.]

Мой компилятор предупреждает о неявной конвертации или приведении определенных типов в bool, тогда как явные преобразования не вызывают предупреждения:

long t = 0;
bool b = false;
b = t;                    // performance warning: forcing long to bool
b = (bool)t;              // performance warning
b = bool(t);              // performance warning
b = static_cast<bool>(t); // performance warning
b = t ? true : false;     // ok, no warning
b = t != 0;               // ok
b = !!t;                  // ok

Это с Visual С++ 2008, но я подозреваю, что другие компиляторы могут иметь похожие предупреждения.

Итак, мой вопрос: какова производительность, влияющая на литье/преобразование на bool? Имеет ли явное преобразование лучшую производительность в некоторых обстоятельствах (например, для определенных целевых архитектур или процессоров)? Неявное преобразование каким-то образом путает оптимизатор?

Microsoft пояснение их предупреждения не особенно полезно. Они подразумевают, что есть веская причина, но они не объясняют это.

Ответ 1

Я был озадачен этим поведением, пока не нашел эту ссылку:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=99633

По-видимому, от разработчика Microsoft, который "владеет" этим предупреждением:

Это предупреждение удивительно полезно, и нашел ошибку в моем коде только вчера. Я думаю, что Мартин принимая "предупреждение о производительности" из контекст.

Это не о сгенерированном коде, это о том, программист сигнализирует о намерении измените значение от int до bool. Для этого есть наказание, и пользователь имеет возможность использовать "int", вместо "bool" последовательно (или скорее наоборот), чтобы избежать "boolifying" codegen. [...]

Это старое предупреждение и может иметь изжили свою цель, но это как и здесь.

Итак, мне кажется, что предупреждение больше о стиле и избегает некоторых ошибок, чем что-либо еще.

Надеюсь, это ответит на ваш вопрос...

: - р

Ответ 2

Производительность идентична по всей доске. Он включает в себя пару инструкций по x86, возможно, 3 на некоторых других архитектурах.

В x86/VС++ все они делают

cmp DWORD PTR [whatever], 0
setne al

GCC генерирует то же самое, но без предупреждений (на любом уровне предупреждения).

Ответ 3

Предупреждение о производительности действительно имеет немного смысл. У меня тоже было это, и мое любопытство привело меня к расследованию с дизассемблером. Он пытается сказать вам, что компилятор должен сгенерировать некоторый код для принуждения значения к 0 или 1. Потому что вы настаиваете на bool, идея старой школы C 0 или что-то еще не применяется.

Вы можете избежать этого крошечного удара производительности, если вы действительно этого хотите. Лучший способ - избегать приведения в целом и использовать bool с самого начала. Если у вас должен быть int, вы можете просто использовать if (int) вместо if (bool). Созданный код будет просто проверять, является ли int 0 или нет. Нет дополнительного кода, чтобы убедиться, что значение равно 1, если оно не будет сгенерировано 0.

Ответ 4

Насколько я знаю, для какого-либо другого компилятора для этого нет предупреждений. Единственный способ, которым я могу думать, что это приведет к потере производительности, заключается в том, что компилятор должен сравнить целое целое число с 0, а затем назначить bool соответствующим образом (в отличие от преобразования, такого как char, в bool, где результат можно скопировать потому что bool - один байт, и поэтому они фактически одинаковы) или интегральное преобразование, которое включает в себя копирование некоторого или всего источника в пункт назначения, возможно, после нулевого адресата, если он больше, чем источник (в терминах память).

Это еще одна из бесполезных и бесполезных идей Microsoft относительно того, что представляет собой хороший код, и заставляет нас мириться с такими глупыми определениями, как это:

template <typename T>
inline bool to_bool (const T& t)
  { return t ? true : false; }

Ответ 5

Звучит как преждевременная оптимизация. Ожидаете ли вы, что производительность броска серьезно повлияет на производительность вашего приложения? Возможно, если вы пишете код ядра или драйверы устройств, но в большинстве случаев все они должны быть в порядке.

Ответ 6

long t;
bool b;
int i;
signed char c;
...

Вы получаете предупреждение, когда делаете что-либо, что было бы "бесплатным", если бы bool не требовалось быть 0 или 1. b =!! t эффективно назначает результат (язык встроенный, не переопределяемый ) bool operator!(long)

Вы не должны ожидать! или!= операторам стоить нулевые инструкции asm даже с оптимизирующим компилятором. Обычно верно, что int я = t обычно оптимизируется полностью. Или даже подписал char c = t; (на x86/amd64, если t находится в регистре% eax, после c = t, используя c просто означает, что% al. amd64 имеет байтовую адресацию для каждого регистра, BTW. IIRC, в x86 в некоторых регистрах нет байтовой адресации.)

В любом случае b = t; i = b; isn't the same as c = t; i = c; it я =!! t; вместо я = t и 0xff;

Err, я думаю, что все уже знают все это из предыдущих ответов. Мое мнение состояло в том, что предупреждение имело смысл для меня, так как оно попадалось в ситуации, когда компилятор должен был делать то, на что вы на самом деле не говорили, например!! BOOL возвращается, потому что вы объявили функцию bool, но возвращаете интегральное значение это может быть верно и!= 1. например много файлов Windows возвращает BOOL (int).

Это одно из сообщений MSVC, которое g++ не имеет. Я больше привык к g++, и он определенно предупреждает о том, что MSVC не делает, но я рад, что это мне рассказывало. Я написал заголовочный файл portab.h с заглушками для классов/макросов/функций MFC/Win32, которые я использовал. Это получило приложение MFC, над которым я работаю, для компиляции на моей машине GNU/Linux дома (и с cygwin). В основном я хотел иметь возможность компилировать-тестировать то, над чем я работал дома, но в итоге я нашел g++-предупреждения очень полезными. Это также намного более строгое, например, шаблоны...

В общем случае, я не уверен, что он делает лучший код при использовании в качестве возвращаемых значений и передачи параметров. Даже для локальных жителей g++ 4.3 не кажется, что он не должен принуждать значение к 0 или 1 перед его ветвлением. Если это локальная переменная, и вы никогда не берете ее адрес, компилятор должен хранить ее в любом размере быстрее всего. Если он должен вытолкнуть его из регистров в стек, он может также сохранить его в 4 байта, так как это может быть немного быстрее. (Он использует множество команд movsx (sign-extension) при загрузке/хранении (нелокальных) bools, но я действительно не помню, что он сделал для переменных автоматического (локального стека). Я помню, что он резервировал нечетные количество стекового пространства (не кратное 4) в функциях, в которых есть некоторые локали bools.)

Использование флагов bool было медленнее, чем int с компилятором Digital Mars D по сравнению с прошлым годом: http://www.digitalmars.com/d/archives/digitalmars/D/opEquals_needs_to_return_bool_71813.html (D очень похож на С++, но отказывается от полной совместимости с обратной связью C, чтобы определить какую-то красивую новую семантику и хорошую поддержку метапрограммирования шаблонов, например, "статические" или "статические", вместо шаблонных хаков или макросов cpp. как дать D попробовать когда-нибудь.:)

Для структур данных это может иметь смысл, например. если вы хотите упаковать пару флагов до int, а затем несколько удвоений в структуре, у вас будет довольно много.

Ответ 7

На основании вашей ссылки на объяснение MS, кажется, что если значение равно только 1 или 0, это не так, но если какое-либо другое значение, отличное от 0, должно быть построено во время компиляции?

Ответ 8

В С++ bool ISA int с двумя значениями 0 = false, 1 = true. Компилятор должен проверять только один бит. Чтобы быть совершенно ясным, true!= 0, поэтому любой int может переопределить bool, это просто обработка циклов обработки для этого.

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

Нет, это не преждевременная оптимизация, совершенно безумно использовать код, который занимает больше времени обработки по всем направлениям. Это просто хорошая практика кодирования.

Ответ 9

Если вы не пишете код для критического внутреннего цикла на самом деле (симулятор ядра, ray-tracer и т.д.), нет смысла беспокоиться о каких-либо результатах производительности в этом случае. В вашем коде есть еще более важные вещи, о которых можно беспокоиться (и я уверен, и другие более значимые ловушки производительности).

Ответ 10

Объяснение Microsoft похоже на то, что они пытаются сказать:

Эй, если вы используете int, но сохранение только истинной или ложной информации в это, сделайте это bool!

Я скептически отношусь к тому, сколько будет достигнуто с точки зрения производительности, но MS, возможно, обнаружила, что в любом случае выигрыш (для их использования). Кодекс Microsoft имеет тенденцию работать очень много, поэтому, возможно, они обнаружили, что микро-оптимизация стоит того. Я считаю, что справедливая часть того, что входит в MS-компилятор, заключается в том, чтобы поддерживать то, что они находят полезными сами (только имеет смысл, правильно?).

И вы избавитесь от каких-то грязных, маленьких бросков для загрузки.

Ответ 11

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