C++ "and"、"&&"和"bitand"之间的区别
C++ difference between "and", "&&" and "bitand"
我想知道以下两者之间的速度或性能是否有任何差异C++:
和操作:&&, and, bitand
手术室操作:||, or, bitor
还是他们所有人的表现都一样?
在详细介绍之前,&&
和and
是等价的,&
和bitand
、||
和or
以及|
和bitor
也是等价的。更多详情请见 cppreference.com
它们之间肯定有区别,所以让我们更详细地看一下它们:
&&
和||
是逻辑运算符。他们的结果要么是true
要么是false
,没有别的。
如果至少一个操作数(||
)或两个操作数(&&
)不false
,则结果true
,false
其他结果。&
和|
是按位运算符。它们独立地操作操作数的每一部分。
这主要用于对数字的位微调操作,例如将数字的最底层 3 位以外的所有位设置为 0(考虑它们的二进制表示):int result1 = number & 0b111; // or to set the 3 lowermost bits to 1 int result2 = number | 0b111;
您可能知道,对于条件语句,C++中的每个数字都可以解释为布尔值,更具体地说,0 是false
,其他所有内容都是true
的。这可能会导致一些混淆,如以下示例所示:
int a = 1;
int b = 2;
if (a && b) {
std::cout << "a && bn";
}
if (a & b) {
std::cout << "a & bn";
}
这将只输出a && b
,因为a & b
是 0,因此false
,即使a
和b
两者都不是false
。
简而言之,使用&&
和||
进行逻辑运算,&
和|
用于数字的按位运算,但要注意副作用:
除了使用范围不同外,这些运算符之间还有另一个区别,即逻辑运算符的强制短路评估(&&
和||
)。这意味着,如果我们已经通过计算第一个操作数知道表达式的结果,则不得计算第二个操作数。这意味着以下两段代码是等效的:
bool result = is_this_true() && is_that_true();
// equivalent:
bool result;
if (is_this_true()) {
result = is_that_true();
} else {
result = false;
}
逻辑或运算符也是如此:
bool result = is_this_true() || is_that_true();
// equivalent:
bool result;
if (is_this_true()) {
result = true;
} else {
result = is_that_true();
}
这是因为
- 如果
&&
的一个操作数是false
,则结果总是false
- 如果
||
的一个操作数是true
,则结果总是true
与按位运算符相比,这肯定会对性能产生影响,基本上有两种不同的方式:
如果
is_that_true()
评估需要大量时间,那么在结果短路的情况下,短路评估可能会节省您的时间。如果
is_this_true()
和is_that_true()
的计算都非常快,但有编译器无法摆脱的副作用,那么等效if
语句引入的额外分支可能会涉及很小的性能损失(有关更多详细信息,请阅读分支错误预测)。但是,在大多数情况下,这种性能差异非常小,除非对这些逻辑运算符的评估是性能瓶颈(同样,这应该非常不可能),否则您永远不必担心它。
如果您想了解更多信息,已经有几个答案详细介绍了短路评估的影响,例如 是否强制要求短路逻辑运算符?和评估顺序?
或者他们所有人的表现都是一样的?
这是一个苹果/橙子的问题。and
和bitand
执行不同的工作。
例:
bool both_nonzero(int x, int y)
{
return x and y;
}
bool have_corresponding_bits(int x, int y)
{
return bool(x bitand y);
}
相应的汇编程序 (gcc-x86_64 -O3):
both_nonzero(int, int):
test edi, edi
setne al
test esi, esi
setne dl
and eax, edx
ret
have_corresponding_bits(int, int):
test edi, esi
setne al
ret
如您所见,第二个函数需要的指令较少,但从 CPU 的角度来看,它正在执行更简单的任务(按位运算是 CPU 一生工作的面包和黄油)。
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- int(c) 和 c-'0' 之间的区别。C++
- C++ 使用 assign 函数的字符串与直接使用 '=' 更改值的字符串之间的区别
- std::atomic和std::condition_variable wait,notify_*方法之间的区别
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 在 const 函数中通过引用和指针返回之间的区别
- 我想知道长双倍和双倍之间的区别
- 这 4 个 lambda 表达式之间有什么区别?
- 结构体 S { int align; } 之间的区别;(struct 关键字后的名称)和 struct { int al
- (double) 和 double() 之间的区别
- & 和 * 之间的区别
- std::is_convertible 和 std::convertible_to 之间的区别(在实践中)?
- 析构函数和'delete'之间的区别
- 在 typedef 内部使用 const 关键字和在 typedef 外部使用 const 关键字之间有区别吗?
- 从预序遍历构造 bst 的 c++ 和 python 解决方案之间的区别
- vector.back() 和 vector[vector.size() - 1] 之间的区别?
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 函数签名与调用的函数不匹配,常量字符[]和字符*之间的区别?
- OpenMP #pragma omp for v/s #pragma omp parallel for 之间的区别?
- S() 与 S{} 之间的区别?