I have a large bitset that I want to frequently reset individual bits in it. Which method is faster?
a) bitset[word_index] ^= 1 << bit_index
or
b) bitset[word_index] &= ~(1 << bit_index)
The application is for the desktop (if that plays a role).
他们不做同样的事情。
选项 a 将翻转给定位;选项 b 将清除它。选择真正反映你意图的那个。如果您想清除该位,但碰巧知道它将始终被设置,我会使用选项 b,因为它更清楚地说明了“清除位”部分。
当你说你想“经常”这样做时——这有多频繁?您是否有任何证据表明这是您的应用程序的瓶颈?如果不是,为什么你对最快的方式而不是最易读的方式感兴趣?
如果您想在位置 N 清除一点,则必须在位置 N 设置一个掩码,在其他位置设置一个 0 和 1,然后使用按位与运算符,如下所示:
a &= ~(1 << N);
如果你想在位置 N 设置一点,你必须在位置 N 设置一个掩码,在其他位置设置一个 1 和 0,然后使用按位 OR 运算符,如下所示:
a |= (1 << N);
如果你想在位置 N 稍微切换一下,你必须在位置 N 设置一个掩码,在其他位置设置一个 0,然后使用按位 XOR 运算符,如下所示:
a ^= (1 << N);
您可以应用相同的推理来一次影响多个位,通常是通过对单个位掩码进行 ORing。例如,要清除 a 中的第 3、第 5 和第 9 位,您可以执行以下操作:
a &= ~( (1 << 3) | (1 << 5) | (1 << 9) );
你为什么要那样做而不是说:
a &= 0x0DD7;
两个原因——
(1) 通常,3、5 和 9 不会是文字,而是为了更好的可读性而定义的常量。(2)编译器无论如何都会在编译时将其转换为(假设您使用常量),无需降低您的代码的可读性。
假设您的代码正确地完成了您的预期:这被称为微优化。
不太可能有任何实质性差异。无论哪种方式,一个好的优化编译器都会产生快速的代码。
建议您在特定情况下进行基准测试。(另外,建议您编写单元测试)