循环中的条件评估?

时间:2009-01-19 09:45:46

标签: c++ loops evaluation conditional-statements

string strLine;//not constant
int index = 0;
while(index < strLine.length()){//strLine is not modified};

评估strLine.length()的次数

我们是否需要在循环之前将nLength分配给nLength使用strLine.length()

9 个答案:

答案 0 :(得分:4)

每次通过循环时都会评估

length,但是由于length是常量时间(O(1)),因此它没有太大区别并且添加了一个用于存储此变量的变量值可能会产生微不足道的影响,因为代码可读性受到轻微打击(如果字符串被更改,则会破坏代码)。

答案 1 :(得分:3)

length()在源文件中包含的头文件中定义,因此它可以由编译器内联,它的内部调用也可以内联,因此如果编译器能够检测到您的字符串实例未被更改在循环中,它可以优化对字符串长度的访问,因此它只会被评估一次。 在任何情况下,我都不认为存储字符串长度的值是非常必要的。也许它可以为你节省一些纳秒,但是你的代码会更大,当你决定在循环中更改字符串时会有一些风险。

答案 2 :(得分:2)

每次调用它......(每次评估时)。 如果你没有改变字符串长度,你最好用一个临时变量,如:

string strLine;
int stringLength = strLine.length();
int index = 0;
while(index < stringLength);

答案 3 :(得分:2)

我认为这里潜藏着第二个问题,那就是“哪个实施更清晰?”

如果从语义上讲,你的意思是strLine的长度永远不会在循环体内发生变化,那么通过指定一个命名良好的变量来明确它。我甚至会把它变成常量。这使得其他程序员(和你自己)明白比较值永远不会改变。

这样做可以让您在调试器中单步执行代码时更容易看到该值。悬停在本地工作比在函数调用上工作好得多。

说,“把它留作函数调用;编译器会对它进行优化”让我觉得过早的悲观化。即使length()是O(1),如果没有内联(你不能保证不会禁用优化),它仍然是一个非常重要的函数调用。通过使用局部变量,您可以阐明您的意思,并获得可能非平凡的性能优化。

做什么使你的意图最清楚。

答案 4 :(得分:1)

strLine.length()将在(i&lt; strLine.length())

的情况下进行评估

说过如果字符串是常量,大多数编译器都会优化它(使用适当的设置)。

答案 5 :(得分:1)

如果要使用时间变量,请使用const限定符,因此编译器可以添加优化,知道该值不会更改:

string strLine;//not constant
int index = 0;
const int strLenght = strLine.Length();
while(index < strLine.length()){//strLine is not modified};

无论如何,编译器本身在访问Length()方法时都会进行优化。

编辑:我的程序集有点生疏,但我认为评估只发生一次。 鉴于此代码:

int main()
{
    std::string strLine="hello world";

    for (int i=0; i < strLine.length(); ++i)
    {
        std::cout << strLine[i] <<std::endl;
    }
}

生成此程序集:

    for (int i=0; i < strLine.length(); ++i)
0040104A  cmp         dword ptr [esp+20h],esi 
0040104E  jbe         main+86h (401086h)

但是对于这段代码

 std::string strLine="hello world";
 const int strLength = strLine.length();
 for (int i=0; i < strLength ; ++i)
 {
    std::cout << strLine[i] <<std::endl;
 }

生成这个:

   for (int i=0; i < strLength ; ++i)
0040104F  cmp         edi,esi 
00401051  jle         main+87h (401087h) 

如果未使用const限定符,则会生成相同的程序集,因此在这种情况下它不会产生任何影响。

尝试使用VSC ++ 2005

答案 6 :(得分:1)

如上所述,由于string::length函数可能完全在头文件中定义,并且需要为O(1),因此几乎可以肯定评估为简单的成员访问,并将内联到您的代码中。由于您没有将字符串声明为volatile,因此允许编译器想象没有外部代码会更改它,并优化对单个内存访问的调用,并将值保留在寄存器中,如果它发现这是一个好主意。

通过自己抓取和缓存值,可以增加编译器执行相同操作的机会。在许多情况下,编译器甚至不会生成将字符串长度写入堆栈的代码,只需将其保留在寄存器中即可。当然,如果你调用编译器无法内联的不同函数,那么必须将值写入堆栈以防止函数调用寄存寄存器。

答案 7 :(得分:0)

由于您没有更改字符串,因此不应该使用

const string strLine;

只是,因为那时编译器会获得更多关于什么可以和什么不能改变的信息 - 不确定C ++编译器究竟有多聪明。

答案 8 :(得分:-1)

每次循环时都会评估

strLine.length()

你是正确的,因为使用nLength会更有效,特别是如果strLine很长。