例如,假设
string s
是这样的:
for(int x = 0; x < s.length(); x++)
比这个更好?:
int length = s.length();
for(int x = 0; x < length; x++)
一般来说,如果结果在迭代过程中没有改变,您应该避免在循环的条件部分中调用函数。
因此规范形式为:
for (std::size_t x = 0, length = s.length(); x != length; ++x);
这里请注意 3 件事:
!=
表示,而不是 <
(我还更改了类型,因为负长度是无意义的,并且字符串接口是根据
std::string::size_type
定义的,在大多数实现中通常是 std::size_t
)。
虽然......我承认它对性能的影响不如对可读性的影响:
x
和length
范围都尽可能严格简而言之:使用最好的工具来完成手头的工作:)
取决于编译器的内联和优化能力。一般来说,第二个变体很可能会更快(更好:它会更快或与第一个片段一样快,但几乎不会慢)。
但是,在大多数情况下这并不重要,因此人们往往更喜欢第一个变体,因为它比较短。
这取决于您的 C++ 实现/库,唯一确定的方法是对其进行基准测试。然而,可以肯定的是,第二个版本永远不会比第一个版本慢,因此,如果您不在循环内修改字符串,那么这是一个明智的优化。
您想要多高效?
如果不在循环内修改字符串,编译器很容易发现大小没有改变。不要让它变得比你需要的更复杂!
虽然我不一定鼓励您这样做,但令人惊讶的是,不断调用
.length()
比将其存储在int
中更快(至少在我的计算机上,请记住我正在使用MSI配备 i5 第四代的游戏笔记本电脑,但它不应该真正影响哪种方式更快)。
持续调用的测试代码:
#include <iostream>
using namespace std;
int main()
{
string g = "01234567890";
for(unsigned int rep = 0; rep < 25; rep++)
{
g += g;
}//for loop used to double the length 25 times.
int a = 0;
//int b = g.length();
for(unsigned int rep = 0; rep < g.length(); rep++)
{
a++;
}
return a;
}
根据 Code::Blocks,平均运行时间为 385 毫秒
这是将长度存储在变量中的代码:
#include <iostream>
using namespace std;
int main()
{
string g = "01234567890";
for(unsigned int rep = 0; rep < 25; rep++)
{
g += g;
}//for loop used to double the length 25 times.
int a = 0;
int b = g.length();
for(unsigned int rep = 0; rep < b; rep++)
{
a++;
}
return a;
}
平均约为 420 毫秒。
我知道这个问题已经有一个公认的答案,但还没有任何经过实际测试的答案,所以我决定投入 2 美分。我和你有同样的问题,但我在这里没有找到任何有用的答案,所以我做了自己的实验。
s.length() 是内联并返回成员变量吗?那么不,否则取消引用并将内容放入堆栈的成本,您知道每次迭代都会产生函数调用的所有开销。