C++避免了位操作的完全转换

hon*_*iao 0 c++ bit

template<class _Diff,
        class _Urng>
        class _Rng_from_urng
    {   // wrap a URNG as an RNG
    public:
        explicit _Rng_from_urng(_Urng& _Func)
            : _Ref(_Func), _Bits(CHAR_BIT * sizeof(_Udiff)), _Bmask(_Udiff(-1))
        {   // construct from URNG
            for (; (_Urng::max)() - (_Urng::min)() < _Bmask; _Bmask >>= 1)
                --_Bits;
        }

        _Diff operator()(_Diff _Index)
        {   // adapt _Urng closed range to [0, _Index)
            for (;;)
            {   // try a sample random value
                _Udiff _Ret = 0;    // random bits
                _Udiff _Mask = 0;   // 2^N - 1, _Ret is within [0, _Mask]

                while (_Mask < _Udiff(_Index - 1))
                {   // need more random bits
                    _Ret <<= _Bits - 1; // avoid full shift
                    _Ret <<= 1;
                    _Ret |= _Get_bits();
                    _Mask <<= _Bits - 1;    // avoid full shift
                    _Mask <<= 1;
                    _Mask |= _Bmask;
                }

                // _Ret is [0, _Mask], _Index - 1 <= _Mask, return if unbiased
                if (_Ret / _Index < _Mask / _Index
                    || _Mask % _Index == _Udiff(_Index - 1))
                    return (_Ret % _Index);
            }
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

上面的代码是从stl粘贴的."避免全班"意味着什么?我认为两位移位可以整合到单个操作中.

_Ret <<= _Bits - 1; // avoid full shift 
_Ret <<= 1;
Run Code Online (Sandbox Code Playgroud)

我将代码更改为:

_Ret<<=_Bits;
Run Code Online (Sandbox Code Playgroud)

这有什么不同?

Swo*_*ish 5

[expr.shift]/1

7.6.7转移运营商

  1. 移位运算符<<和>>组从左到右.

    移位表达:

    添加剂的表达

    shift-expression << additive-expression

    shift-expression >> additive-expression

    操作数应为整数或无范围的枚举类型,并执行整体促销.结果的类型是提升的左操作数的类型.如果右操作数为负数,或者大于或等于提升左操作数的位长度,则行为未定义.

  • I. e.如果`_Bits`等于`sizeof(_Udiff)*CHAR_BIT`,则转换被分成两个以避免未定义的行为,如果构造函数中的for循环未被*输入,则可能发生这种情况. (2认同)