我知道未初始化的局部变量是未定义的行为(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);
    }
}

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


当前回答

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

其他回答

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

A_Function_that_use_a_lot_the_Stack();
updateEffect();

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

不,太糟糕了。

使用未初始化变量的行为在C和c++中都是未定义的,而且这样的方案不太可能具有理想的统计属性。

如果你想要一个“快速而肮脏”的随机数生成器,那么rand()是你最好的选择。在它的实现中,它所做的只是一个乘法、一个加法和一个模数。

我所知道的最快的生成器需要你使用uint32_t作为伪随机变量I的类型,并使用

I = 1664525 * I + 1013904223

生成连续的值。你可以选择任何你喜欢的I的初始值(称为种子)。显然你可以内联编码。无符号类型的标准保证包装充当模数。(数字常数是由杰出的科学程序员Donald Knuth精心挑选的。)

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

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

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

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

There are certain situations in which uninitialized memory may be safely read using type "unsigned char*" [e.g. a buffer returned from malloc]. Code may read such memory without having to worry about the compiler throwing causality out the window, and there are times when it may be more efficient to have code be prepared for anything memory might contain than to ensure that uninitialized data won't be read (a commonplace example of this would be using memcpy on partially-initialized buffer rather than discretely copying all of the elements that contain meaningful data).

然而,即使在这种情况下,人们也应该始终假设,如果字节的任何组合特别烦人,那么读取它总是会产生字节的模式(如果某个模式在生产中是烦人的,但在开发中不是,那么这种模式直到代码进入生产中才会出现)。

Reading uninitialized memory might be useful as part of a random-generation strategy in an embedded system where one can be sure the memory has never been written with substantially-non-random content since the last time the system was powered on, and if the manufacturing process used for the memory causes its power-on state to vary in semi-random fashion. Code should work even if all devices always yield the same data, but in cases where e.g. a group of nodes each need to select arbitrary unique IDs as quickly as possible, having a "not very random" generator which gives half the nodes the same initial ID might be better than not having any initial source of randomness at all.

好问题!

未定义并不意味着它是随机的。考虑一下,在全局未初始化变量中获得的值是由系统或您的/其他应用程序运行时遗留在那里的。根据您的系统对不再使用的内存的处理和/或系统和应用程序生成的值类型,您可能会得到:

总是一样的。 成为一小部分价值观中的一员。 获取一个或多个小范围内的值。 在16/32/64位系统的指针上看到许多可以被2/4/8整除的值 ...

您将得到的值完全取决于系统和/或应用程序留下的非随机值。因此,确实会有一些噪音(除非您的系统删除不再使用的内存),但您将从中提取的值池绝不是随机的。

对于局部变量,情况会变得更糟,因为它们直接来自您自己程序的堆栈。在执行其他代码期间,您的程序很有可能实际编写这些堆栈位置。我估计在这种情况下运气的机会非常低,而你所做的“随机”代码更改将尝试这种运气。

阅读随机性。正如你所看到的,随机性是一种非常特殊且难以获得的属性。一个常见的错误是,如果你只是采取一些难以跟踪的东西(比如你的建议),你会得到一个随机的值。