Почему существует предупреждение о производительности для указателя на bool?
Расширяет.
Я думал, что я был классным, когда я сделал что-то вроде:
bool hasParent()
{
return this->parentNode ;
}
Даже при использовании (bool) предупреждение все равно не исчезает.
Если this- > parentNode равен NULL, если родительский node отсутствует.
Но я получаю:
warning C4800: 'Node *' : forcing value to bool 'true' or 'false' (performance warning)
Какая сделка, лет? Почему это предупреждение о производительности? Я думал, что было бы более эффективно не писать что-то вроде:
bool hasParent()
{
if( this->parentNode )
return true ;
else
return false ;
}
Но вторая версия не генерирует никаких предупреждений, а компилятор кажется намного счастливее. Что быстрее, хотя?
Ответы
Ответ 1
Здесь обсуждается Microsoft Connect об этом (Какова производительность преобразования в bool на С++?). Пример, предоставленный 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" последовательно (или, скорее, наоборот), чтобы избежать "boolifying" codegen. Предупреждение подавляется в третьем случае ниже, потому что он ясно сигнализировал о своем намерении принять переход int- > bool.
Это старое предупреждение и, возможно, изжило его цель, но оно ведет себя так, как здесь описано
Таким образом, в основном разработчик MS, похоже, говорит, что если вы хотите "сбрасывать" int
в bool
, вы должны более правильно его использовать, используя "return this->parentNode != 0
" вместо неявного или явного приведения.
Лично мне было бы интересно узнать больше о том, какие ошибки обнаруживает предупреждение. Я думаю, что это предупреждение не имело бы большой ценности.
Ответ 2
Тот факт, что кастинг на bool
не выводит предупреждение по дизайну:
Листинг выражения типа bool не отключит предупреждение, которое по дизайну.
Я бы порекомендовал подход, который в описании MSDN предупреждения C4800 рекомендует:
return this->parentNode != NULL;
это дает понять, что вы возвращаете true
, если parentNode
не является нулевым указателем и false
, если parentNode
является нулевым указателем.
Ответ 3
Компилятор должен сгенерировать дополнительный код для преобразования указателя в 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
Это не видно непосредственно из источника, поэтому компилятор считает, что это то, о чем следует предупреждать пользователя.
Ответ 4
Почему это предупреждение о производительности?
Компилятор поворачивает это:
bool hasParent()
{
return this->parentNode;
}
в
bool hasParent()
{
return this->parentNode != 0;
}
Это занимает примерно один такт больше, чем вы могли бы ожидать от просмотра кода. Это незначительная разница в производительности.
Я думаю, что лучше всего выписать != 0
в явном виде, так как это делает код более понятным, а также отключает предупреждение.
Ответ 5
Было бы более удобно писать:
bool hasParent()
{
return this->parentNode != NULL;
}
Ответ 6
Я уверен, что это зависит от компилятора
Ответ 7
В реальности я думаю, что они будут оптимизированы к тому же, вы также можете попробовать сделать это:
return this->parentNode != 0;