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

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


当前回答

如果操作得当,使用未初始化的数据来获得随机性并不一定是件坏事。事实上,OpenSSL正是这样做的,以播种它的PRNG。

显然,这种用法并没有很好地记录下来,因为有人注意到Valgrind抱怨使用未初始化的数据,并“修复”了它,导致了PRNG中的一个错误。

所以你可以这样做,但你需要知道你在做什么,并确保任何阅读你的代码的人都理解这一点。

其他回答

还没有提到,但是调用未定义行为的代码路径可以做编译器想做的任何事情,例如:

void updateEffect(){}

这肯定比你正确的循环快,因为有UB,是完全符合的。

由于安全原因,必须清理分配给程序的新内存,否则信息可能会被使用,密码可能会从一个应用程序泄漏到另一个应用程序。只有在重用内存时,才会得到不同于0的值。很有可能,在堆栈上,前一个值是固定的,因为前一个内存的使用是固定的。

正如其他人已经提到的,这是未定义的行为(UB),但它可能“有效”。

除了其他人已经提到的问题之外,我还看到了另一个问题(缺点)——它不能在C和c++以外的任何语言中工作。我知道这个问题是关于c++的,但是如果你能写出好的c++代码和Java代码,这不是问题,那为什么不呢?也许有一天有人将不得不将其移植到其他语言,并且搜索像这样的“魔术”UB所导致的错误绝对是一场噩梦(特别是对于没有经验的C/ c++开发人员)。

这里有一个关于另一个类似UB的问题。想象一下,你试图在不知道这个UB的情况下找到这样的bug。如果你想阅读更多关于C/ c++中这些奇怪的东西,请阅读链接中的问题答案,并查看这个很棒的幻灯片。它将帮助你理解引擎盖下面是什么以及它是如何工作的;这不仅仅是另一个充满“魔力”的幻灯片。我确信即使是大多数有经验的C/c++程序员也能从中学到很多东西。

正如其他人所注意到的,这就是未定义行为(UB)。

实际上,它(可能)实际上(有点)管用。在x86[-64]架构上读取未初始化的寄存器确实会产生垃圾结果,而且可能不会做任何坏事(与例如Itanium相反,那里的寄存器可以被标记为无效,因此读取会传播NaN之类的错误)。

但这里存在两个主要问题:

It won't be particularly random. In this case, you're reading from the stack, so you'll get whatever was there previously. Which might be effectively random, completely structured, the password you entered ten minutes ago, or your grandmother's cookie recipe. It's Bad (capital 'B') practice to let things like this creep into your code. Technically, the compiler could insert reformat_hdd(); every time you read an undefined variable. It won't, but you shouldn't do it anyway. Don't do unsafe things. The fewer exceptions you make, the safer you are from accidental mistakes all the time.

UB更紧迫的问题是它使整个程序的行为没有定义。现代编译器可以使用它来省略大量的代码,甚至可以回溯到过去。玩UB就像维多利亚时代的工程师拆除一个活跃的核反应堆。有无数的事情会出错,而且您可能连一半的基本原则或实现的技术都不知道。这可能没什么,但你仍然不应该让它发生。看看其他漂亮的答案来了解细节。

还有,我会炒了你。

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

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

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

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

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

我也不会解雇你。