用这种方式将整数转换为布尔值的原因可能是什么?
bool booleanValue = !!integerValue;
而不只是
bool booleanValue = integerValue;
我所知道的是,在VC ++ 7中,后者将导致C4800警告,而前者则不会。两者之间还有其他区别吗?
用这种方式将整数转换为布尔值的原因可能是什么?
bool booleanValue = !!integerValue;
而不只是
bool booleanValue = integerValue;
我所知道的是,在VC ++ 7中,后者将导致C4800警告,而前者则不会。两者之间还有其他区别吗?
Answers:
与“!”的问题 成语是简洁,难以看清,容易将错字误认为,容易丢掉“!”之一等等。我把它放在“看起来我们在C / C ++中能有多可爱”类别。
只是写bool isNonZero = (integerValue != 0);
...要清楚。
!!
技巧,显式比较(或强制转换)绝对是更可取的选择。
从历史上看,该!!
惯用法用于确保布尔bool
变量确实包含-like变量中预期的两个值之一,因为C和C ++没有真正的bool
类型,我们使用int
s进行了伪造。现在,对于“ real”而言,这不再是一个问题bool
。
但是,使用!!
是一种非常有效的文档编制方法(对于编译器和任何将来在代码中工作的人员而言),是的,您确实打算将其int
转换为bool
。
List<String>
意思||=
。!!
是C和C ++领域中非常非常根深蒂固的习语。如果谁不知道,他/她应该学习它-然后对是否使用它进行自己的合理评估。
因为!integerValue表示integerValue == 0,而!! integerValue表示integerValue!= 0,所以返回布尔的有效表达式。后者是信息丢失的演员。
另一个选择是三元运算符,它看起来生成的汇编代码少一行(无论如何在Visual Studio 2005中):
bool ternary_test = ( int_val == 0 ) ? false : true;
产生汇编代码:
cmp DWORD PTR _int_val$[ebp], 0
setne al
mov BYTE PTR _ternary_test$[ebp], al
与:
bool not_equal_test = ( int_val != 0 );
产生:
xor eax, eax
cmp DWORD PTR _int_val$[ebp], 0
setne al
mov BYTE PTR _not_equal_test$[ebp], al
我知道这并没有太大的区别,但是我对此感到很好奇,只是想分享一下我的发现。
一个布尔型只能具有两个状态0和1。一个整数可以具有从-2147483648到2147483647的任何状态(假设有符号的32位整数)。一元!如果输入为0,则运算符输出1;如果输入为0,则运算符输出0。因此!0 = 1和!234 = 0。只需切换输出,以便0变为1且1变为0。
因此,第一条语句保证将booleanValue设置为等于0或1,并且没有其他值,第二条语句则没有。
int
->bool
强制转换。这是定义明确的,任何非零int
都将转换为true
,而0将转换为false
。VC ++给出的警告实际上是“性能警告”,与之无关。
!!
是转换为的惯用方式bool
,它可以关闭Visual C ++编译器关于所谓的转换效率低下的愚蠢警告。
通过其他答案和评论,我看到许多人不熟悉该惯用法在Windows编程中的用处。这意味着他们还没有进行任何认真的Windows编程。并盲目假设他们所遇到的是具有代表性的(不是)。
#include <iostream>
using namespace std;
int main( int argc, char* argv[] )
{
bool const b = static_cast< bool >( argc );
(void) argv;
(void) b;
}
> [d:\ dev \ test] > cl foo.cpp foo.cpp foo.cpp(6):警告C4800:'int':强制将值设置为'true'或'false'(性能警告) [d:\ dev \ test] > _
至少有人认为,如果一个新手根本不认识它的意思,那就不好了。好吧,这很愚蠢。很多新手根本不认识或理解。编写代码以使任何新手都能理解它对于专业人士而言不是一件容易的事。甚至没有学生。从排除说出新手不认识的运算符和运算符组合的路径开始……好吧,我没有合适的描述来表达这种方法,对不起。
user143506的答案是正确的,但针对可能的性能问题,我比较了asm中的可能性:
return x;
,return x != 0;
,return !!x;
甚至return boolean_cast<bool>(x)
在这一套完美的汇编指令的结果:
test edi/ecx, edi/ecx
setne al
ret
已针对GCC 7.1和MSVC 19 2017进行了测试。(仅MSVC 19 2017中的boolean_converter导致大量的asm代码,但这是由模板化和结构引起的,并且在性能方面可以忽略,因为相同如上所述的行可能会在相同的运行时间中针对不同的功能进行重复。)
这意味着:没有性能差异。
PS:使用了此boolean_cast:
#define BOOL int
// primary template
template< class TargetT, class SourceT >
struct boolean_converter;
// full specialization
template< >
struct boolean_converter<bool, BOOL>
{
static bool convert(BOOL b)
{
return b ? true : false;
}
};
// Type your code here, or load an example.
template< class TargetT, class SourceT >
TargetT boolean_cast(SourceT b)
{
typedef boolean_converter<TargetT, SourceT> converter_t;
return converter_t::convert(b);
}
bool is_non_zero(int x) {
return boolean_cast< bool >(x);
}
除了被偏执狂或通过代码大吼大叫外,没有什么大的理由。
对于编译器最终不会有所作为。
我从不喜欢这种转换为bool
数据类型的技术-闻起来很错!
取而代之的是,我们使用了一个名为boolean_cast
found here的便捷模板。这是一个灵活的解决方案,它在做什么方面更加明确,可以按以下方式使用:
bool IsWindow = boolean_cast< bool >(::IsWindow(hWnd));