在 while 循环中使用条件语句排序

6

首先,在开始之前,我使用VC++ 2008专业版,在Windows操作系统上运行Intel Core2。我知道这段代码永远不会在除Core2/Corei7以外的任何设备上执行。

我有一个带有两个条件的while循环,大致如下:

注意:这是一个简化版本。

while((a != b) && (array[a] < c))

如果第一个条件 (a != b) 生成 false,第二个条件会被评估吗?还是循环会在那里终止?
我进行了几次测试,似乎确实如此。
然而,问题在于:如果第一个条件评估为 false,第二个条件将生成访问冲突。但是,从我所看到的情况来看,一旦第一个条件被评估为 false,程序就不再费力去评估第二个条件并退出循环,从而拯救了我。
问题在于,我无法摆脱访问违规问题,否则我的代码将变得非常糟糕。但是,由于这个小“漏洞”(我知道这是编译器优化,而不是漏洞),我似乎能够逃避它。我也知道这可能不是好的编程实践,但老实说,在我的情况下,如果它起作用,我已经赢得了游戏。
我的问题是,这个“漏洞”或编程不当的行为有没有可能在某一天反咬我一口?即使考虑到我对此部分进行了彻底的测试,并且只会使用它一次?

哇,你有很多问题啊!你应该加我的 Messenger 哈哈。 - John T
你又来了!我会在 MM 上给你发消息并把我的 Messenger 给你。伙计,你那边已经是凌晨 3 点了!你不睡觉吗?你就住在这里吗?(我这么晚还醒着只是因为这是唯一其他人都睡觉不打扰我的时间,所以我可以在我的论文上做些工作)。 - Faken
我定期检查我的几个网站,你的问题总是引起我的兴趣,并且总是在页面的顶部附近。这有点吓人了。我现在早起了-两个小时后去健身房。 - John T
6个回答

24

只有当第一个条件评估为true时,才会评估第二个条件。您可以信赖这一点。由于这是C和C ++如何执行短路逻辑表达式评估的方式,因此数百万行代码都可以工作。

您可以使用它,并且可以信赖它。如果第一个表达式评估为false,则第二个表达式甚至不会开始评估。


3
即使第二个条件在导致第一个条件返回false的状态下被评估而可能导致程序崩溃,这样使用是否可以? - Faken
是的,任何符合标准的C++实现都会保证这一点。 - sharptooth
1
@Faken - 是的,没问题。别担心! - George Phillips
如果有帮助的话,Faken,可以这样看待:C++标准禁止任何实现在LHS为false时评估RHS。因此,编译器不仅仅是“不会”评估它。按照RFC术语,它必须不评估它。 - Steve Jessop
while(f()-g()); 这个怎么样?f() 会在 g() 之前被调用吗?这与编译器有关吗? - e271p314
显示剩余2条评论

4

这不是一个bug。C++使用短路求值,所以当第一个条件为假时,第二个条件将不会被评估。


2

它不会被评估。然而,如果您担心您编写的程序例程会给您带来麻烦,那么您应该重新评估您所编写的内容。您已经承认这是不良的编程实践。您已经知道这将成为一个问题。当满足这些条件时,只需修复问题即可。明天早上您会更少地讨厌自己。


我明白,但是我写的那13行简洁明了的代码依赖于这个才能正常工作...如果我修复它,我将失去很多,非常多的速度和效率。当我说非常多时,我的意思是代码执行会变得慢2-3倍。 - Faken
别担心。我们也会根据短路评估来编写代码。你不会期望当循环条件一开始就为假时,while循环会启动吧?这里也是同样的道理。 - sharptooth
我很感兴趣,为什么你认为这是一种糟糕的编程实践? - CB Bailey

2
该语言保证了这种短路行为,因此您使用它时无需担心。它也适用于|| - 如果第一个条件为true,则不会评估第二个条件。

1

依赖于C++逻辑AND和OR运算符的短路行为不应被视为一种不良实践。这是完全惯用的,通常会导致更清晰、更简洁的代码。

例如:

std::auto_ptr< SomeObject > data;

使用短路运算符 &&

// Clear expired data, if present
if( data.get() && data->expired )
    data.reset();

如果不使用短路运算符&&,就需要额外的一层if语句,这会导致代码更加冗长。

// Clear expired data, if present
if( data.get() )
{
    if ( data->expired )
        data.reset();
}

1
第二个条件在第一个条件不成立时将不会被评估。 正如您所说,这种优化是所有C++编译器都遵循的。
如果您仍然无法理解,请在while循环中添加一个简单的if语句。
while ( a != b ) {
    if ( array[a] < c )
    {
         // your code goes here.
    }
    else
    {
        break;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接