在循环中使用 string.length() 是否有效?

发布于 2024-10-19 11:18:04 字数 204 浏览 8 评论 0原文

例如,假设 string s 是这样的:

for(int x = 0; x < s.length(); x++)

比这个更好?:

int length = s.length();
for(int x = 0; x < length; x++)

For example, assuming a string s is this:

for(int x = 0; x < s.length(); x++)

better than this?:

int length = s.length();
for(int x = 0; x < length; x++)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

つ低調成傷 2024-10-26 11:18:04

一般来说,如果结果在迭代期间没有改变,您应该避免在循环的条件部分中调用函数。

因此,规范形式是:

for (std::size_t x = 0, length = s.length(); x != length; ++x);

这里注意 3 件事:

  • 初始化可以初始化多个变量
  • 条件用 != 表示,而不是 <
  • 我使用预增量而不是比后增量

(我还更改了类型,因为负长度是无意义的,并且字符串接口是根据 std::string::size_type 定义的,通常是 std ::size_t 大多数实现)。

虽然......我承认它对性能的影响不如对可读性的影响:

  • 双重初始化意味着 xlength 范围都尽可能严格
  • 通过记住结果读者不会怀疑迭代过程中长度是否会发生变化
  • 当您不需要创建具有“旧”值的临时值时,使用预增量通常会更好

简而言之:使用适合工作的最佳工具就在眼前:)

In general, you should avoid function calls in the condition part of a loop, if the result does not change during the iteration.

The canonical form is therefore:

for (std::size_t x = 0, length = s.length(); x != length; ++x);

Note 3 things here:

  • The initialization can initialize more than one variable
  • The condition is expressed with != rather than <
  • I use pre-increment rather than post-increment

(I also changed the type because is a negative length is non-sense and the string interface is defined in term of std::string::size_type, which is normally std::size_t on most implementations).

Though... I admit that it's not as much for performance than for readability:

  • The double initialization means that both x and length scope is as tight as necessary
  • By memoizing the result the reader is not left in the doubt of whether or not the length may vary during iteration
  • Using pre-increment is usually better when you do not need to create a temporary with the "old" value

In short: use the best tool for the job at hand :)

听不够的曲调 2024-10-26 11:18:04

这取决于编译器的内联和优化能力。一般来说,第二个变体很可能会更快(更好:它会更快或与第一个片段一样快,但几乎不会慢)。

然而,在大多数情况下,这并不重要,因此人们倾向于选择第一个变体,因为它的简短性。

It depends on the inlining and optimization abilities of the compiler. Generally, the second variant will most likely be faster (better: it will be either faster or as fast as the first snippet, but almost never slower).

However, in most cases it doesn't matter, so people tend to prefer the first variant for its shortness.

沉睡月亮 2024-10-26 11:18:04

这取决于您的 C++ 实现/库,唯一确定的方法是对其进行基准测试。然而,可以肯定的是,第二个版本永远不会比第一个版本慢,因此,如果您不在循环内修改字符串,那么这是一个明智的优化。

It depends on your C++ implementation / library, the only way to be sure is to benchmark it. However, it's effectively certain that the second version will never be slower than the first, so if you don't modify the string within the loop it's a sensible optimisation to make.

肩上的翅膀 2024-10-26 11:18:04

您希望效率如何?

如果不在循环内修改字符串,编译器很容易发现大小没有改变。不要让它变得比你需要的更复杂!

How efficient do you want to be?

If you don't modify the string inside the loop, the compiler will easily see than the size doesn't change. Don't make it any more complicated than you have to!

神经大条 2024-10-26 11:18:04

s.length() 是内联并返回成员变量吗?那么不,否则取消引用并将内容放入堆栈的成本,您知道每次迭代将产生的函数调用的所有开销。

Is s.length() inline and returns a member variable? then no, otherwise cost of dereferencing and putting stuff in stack, you know all the overheads of function call you will incur for each iteration.

计㈡愣 2024-10-26 11:18:04

尽管我不一定鼓励您这样做,但似乎不断调用 .length() 比将其存储在 int 中更快,令人惊讶的是(至少在我的计算机,请记住,我使用的是配备 i5 第四代的 MSI 游戏笔记本电脑,但它应该不会真正影响哪种方式更快)。

常量调用的测试代码:

#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 美分。我和你有同样的问题,但我在这里没有找到任何有用的答案,所以我做了自己的实验。

Although I am not necessarily encouraging you to do so, it appears it is faster to constantly call .length() than to store it in an int, surprisingly (atleast on my computer, keeping in mind that I'm using an MSI gaming laptop with i5 4th gen, but it shouldn't really affect which way is faster).

Test code for constant call:

#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;
}

On average, this ran for 385ms according to Code::Blocks

And here's the code that stores the length in a variable:

#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;
}

And this averaged around 420ms.

I know this question already has an accepted answer, but there haven't been any practically tested answers, so I decided to throw my 2 cents in. I had the same question as you, but I didn't find any helpful answers here, so I ran my own experiment.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文