我知道未初始化的局部变量是未定义的行为(UB),而且值可能有陷阱表示,这可能会影响进一步的操作,但有时我想使用随机数仅为视觉表示,而不会在程序的其他部分进一步使用它们,例如,在视觉效果中设置随机颜色的东西,例如:

void updateEffect(){
    for(int i=0;i<1000;i++){
        int r;
        int g;
        int b;
        star[i].setColor(r%255,g%255,b%255);
        bool isVisible;
        star[i].setVisible(isVisible);
    }
}

比那么快吗

void updateEffect(){
    for(int i=0;i<1000;i++){
        star[i].setColor(rand()%255,rand()%255,rand()%255);
        star[i].setVisible(rand()%2==0?true:false);
    }
}

也比其他随机数生成器快吗?


当前回答

真的不好!坏习惯,坏结果。 考虑:

A_Function_that_use_a_lot_the_Stack();
updateEffect();

如果函数A_Function_that_use_a_lot_the_Stack()总是进行相同的初始化,则堆栈上保留相同的数据。这些数据就是我们调用updateEffect()得到的:总是相同的值!

其他回答

还有一种可能性需要考虑。

现代编译器(嗯,g++)非常聪明,它们会检查你的代码,看看哪些指令影响状态,哪些不影响状态,如果一条指令被保证不影响状态,g++会简单地删除那条指令。

接下来会发生什么。g++肯定会看到你正在读取,执行算术运算,保存,本质上是一个垃圾值,这会产生更多的垃圾。因为不能保证新的垃圾会比旧的垃圾更有用,所以它只会让你的循环消失。杂音!

这个方法很有用,但下面是我要做的。结合UB(未定义行为)与rand()速度。

当然,reduce rand()被执行了,但是把它们混合在一起,这样编译器就不会做任何你不希望它做的事情。

我也不会解雇你。

未定义的行为意味着编译器的作者可以自由地忽略这个问题,因为无论发生什么,程序员都没有权利抱怨。

理论上,当进入UB域时,任何事情都可能发生(包括守护进程从你鼻子上飞出去),通常意味着编译器作者不会关心,对于局部变量,其值将是当时堆栈内存中的任何值。

这也意味着内容通常是“奇怪的”,但是是固定的,或者是稍微随机的,或者是可变的,但是有一个清晰的模式(例如,在每次迭代中增加值)。

当然,你不能指望它是一个不错的随机生成器。

把我们的逻辑依赖于语言未定义的行为不是一个好主意。除了在这篇文章中所提到/讨论的内容之外,我想提到的是,使用现代c++方法/风格,这样的程序可能无法编译。

这在我之前的文章中提到过,其中包含了自动功能的优势和相同的有用链接。

https://stackoverflow.com/a/26170069/2724703

因此,如果我们改变上面的代码并用auto替换实际的类型,程序甚至无法编译。

void updateEffect(){
    for(int i=0;i<1000;i++){
        auto r;
        auto g;
        auto b;
        star[i].setColor(r%255,g%255,b%255);
        auto isVisible;
        star[i].setVisible(isVisible);
    }
}

正如这里大多数人提到的未定义行为。未定义也意味着你可以得到一些有效的整数值(幸运的是),在这种情况下,这将更快(因为rand函数调用没有进行)。 但不要实际使用它。我相信这将会带来可怕的结果,因为运气并不总是伴随着你。

在任何想要使用未初始化变量的地方使用7757。我从质数列表中随机选择了它:

这是被定义的行为 它保证不总是0 它是质数 它很可能在统计上是随机的,就像未初始化一样 变量 它可能比未初始化的变量快,因为它的 值在编译时已知