Почему существует предупреждение о производительности при приведении указателя на bool?
Я думал, что я был крут, когда я сделал что-то вроде:
bool hasParent() { return this->parentNode ; }
даже с A (bool) cast, предупреждение все еще не уходит.
где это - > parentNode имеет значение NULL, когда нет родительского узла.
но я получаю:
warning C4800: 'Node *' : forcing value to bool 'true' or 'false' (performance warning)
в чем дело, йо? Почему это предупреждение о производительности? Я думал, что было бы более эффективно не писать что-то вроде:
bool hasParent() { if( this->parentNode ) return true ; else return false ; }
но второй версия генерирует никаких предупреждений и компилятор, кажется, намного счастливее. Что быстрее, хотя?
7 ответов:
есть обсуждение на Microsoft Connect об этом (какова производительность преобразования в bool в C++?). Пример, приведенный в Microsoft:
$ cat -n t.cpp && cl -c -W3 -O2 -nologo -Fa t.cpp 1 bool f1 (int i) 2 { 3 return i & 2; 4 } 5 6 bool f2 (int i) 7 { 8 const bool b = i & 2; 9 return b; 10 } 11 12 bool f3 (int i) 13 { 14 const bool b = 0 != (i & 2); 15 return b; 16 } t.cpp t.cpp(3) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning) t.cpp(8) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning)
и ответ Microsoft (от разработчика, ответственного за предупреждение):
это предупреждение удивительно полезно, и нашел ошибку в моем коде только вчера. Я думаю, что Мартин берет "предупреждение о производительности" из контекста.
дело не в этом сгенерированный код, это о том, сигнализировал ли программист о намерении изменить значение с int на bool. Существует штраф за это, и у пользователя есть выбор использовать "int" вместо "bool" последовательно (или, скорее всего, наоборот), чтобы избежать "логического" codegen. Предупреждение подавляется в третьем случае ниже, потому что он явно сигнализировал о своем намерении принять переход int->bool.
это старое предупреждение, и, возможно, изжило свою цель, но он ведет себя так, как задумано здесь
так что в основном разработчик MS, похоже, говорит, что если вы хотите "бросить"
int
tobool
вы должны более правильно делать это с помощью "return this->parentNode != 0
" вместо неявного или явного приведения.лично мне было бы интересно узнать больше о том, какие ошибки предупреждение раскрывает. Я думаю, что это предупреждение не будет иметь большого значения.
дело в том, что кастинг на
bool
не делает предупреждение уйти по проекту:приведение выражения к типу bool не отключит предупреждение, которое по дизайну.
Я бы рекомендовал подход, который рекомендует описание MSDN предупреждения C4800:
return this->parentNode != NULL;
это дает понять, что вы возвращаетесь
true
ЕслиparentNode
не является нулевым указателем иfalse
еслиparentNode
- нулевой указатель.
компилятор должен генерировать дополнительный код для конвертации указателя в bool. Это в основном сравнение с нулем и установка результата на один, если не ноль.
00000000004005e0 <_Z4testPv>: bool test(void* adr) { 4005e0: 48 85 ff test %rdi,%rdi 4005e3: 0f 95 c0 setne %al return adr; } 4005f8: c3 retq
это не видно непосредственно из источника, поэтому компилятор считает, что это то, о чем пользователь должен быть предупрежден.
Почему это предупреждение о производительности?
компилятор превращает этот:
bool hasParent() { return this->parentNode; }
в:
bool hasParent() { return this->parentNode != 0; }
это займет около часы больше, чем вы могли бы ожидать, глядя на код. Это незначительная разница в производительности.
Я думаю, что лучше написать
!= 0
явно в любом случае, так как это делает код более ясным, а также глушит предупреждение.