C++ 为什么在c++;

C++ 为什么在c++;,c++,bitwise-operators,C++,Bitwise Operators,我很难理解为什么要在枚举中使用位运算 然后在代码中。 为什么不只用数字或布尔值呢 例如: enum { RS_BLEND = (1 << 0), RS_BLEND_FUNC = (1 << 1), RS_CULL_FACE = (1 << 2), RS_DEPTH_TEST = (1 << 3), RS_DEPTH_WRITE = (1 << 4), RS_DEPTH_FUNC = (1

我很难理解为什么要在枚举中使用位运算 然后在代码中。 为什么不只用数字或布尔值呢 例如:

enum
{
    RS_BLEND = (1 << 0),
    RS_BLEND_FUNC = (1 << 1),
    RS_CULL_FACE = (1 << 2),
    RS_DEPTH_TEST = (1 << 3),
    RS_DEPTH_WRITE = (1 << 4),
    RS_DEPTH_FUNC = (1 << 5),
    RS_CULL_FACE_SIDE = (1 << 6),
//            RS_STENCIL_TEST = (1 << 7),
//            RS_STENCIL_WRITE = (1 << 8),
//            RS_STENCIL_FUNC = (1 << 9),
//            RS_STENCIL_OP = (1 << 10),
    RS_FRONT_FACE = (1 << 11),

    RS_ALL_ONES = 0xFFFFFFFF,
};


void RenderState::StateBlock::setCullFace(bool enabled)
{
    _cullFaceEnabled = enabled;
    if (!enabled)
    {
        _bits &= ~RS_CULL_FACE;
    }
    else
    {
        _bits |= RS_CULL_FACE;
    }
}
enum
{

RS_BLEND=(1使用位而不是布尔值的优点是,您可以直接操作组值

const int FILLED  = (1 << 0);
const int STROKED = (1 << 1);
const int SHADOW  = (1 << 2);
const int BLINK   = (1 << 3);
i、 e.直接传递值的子集


使用容器而不是单个整数参数将需要更多的代码来写入和读取。这也会降低效率,但在某些情况下,这并不是最重要的一点。

这些枚举值是位字段中使用的标志(此处为
\u bits
)。通过声明布尔结构可以获得类似的行为:

struct field {
    bool rs_blend;
    bool rs_blend_func;
    ...
};
然而,这样的结构要求每个条目至少有一个字节,而且处理起来很困难,因此开发人员采用了不同的方法,将这些值编码为整数值的位


任何值为1的整数都有“最右边”(最低有效)的位集,因此
11位而不是8位(如果您使用布尔值)。使用1/8的内存来表示完全相同的数据是一个非常惊人的节约(并且仅仅因为某人对按位操作感到不舒服而使用8倍以上的内存同样是非常浪费的),如果您正在处理循环中频繁访问的热数据,这可能很重要(我的i7上每个一级缓存核心只有64KB,例如,更不用说有限的寄存器)

此外,如果您在这里使用位,您可以测试使用单个指令设置的两个或更多位。您还可以使用FFZ/FFS一次有效地在64位中找到一个空闲位或一个集合位。您可以轻松地反转,比如说,一次反转64位,而不是循环通过64个布尔值,并且必须一次执行一个,这不仅令人难以置信对于CPU来说是高效的,但是对于开发人员来说,当他只需要一个操作符时,编写所有代码的效率和生产率都会降低

好处还在继续。我实际上认为应该有更多的人使用逐位运算,而不是更少。习惯于按位思考需要一些时间,但不会花太长时间。

这很方便

在示例代码中,显然(包括注释中的内容)至少有12个不同的设置,每个设置都是打开或关闭的,但可以组合打开或关闭

位摆弄允许打开或关闭单个设置组(包括一组设置),或者测试特定组是否打开或关闭,而无需大惊小怪

数值和数值操作可以做到这一点,但并不是那么方便

例如,如果使用“CULL_FACE”和“DEPTH_FACE”设置中至少有一个处于启用状态,则测试更容易(且更不容易出错)

 if (flags & (RS_CULL_FACE | RS_DEPTH_FACE))
然后跟踪这两个设置中的一个可能为真的所有可能的数值,并针对每一个进行测试。

它被用作一个。您将如何编写它?
 if (flags & (RS_CULL_FACE | RS_DEPTH_FACE))