多次调用访问器方法或声明临时变量是否更有效

Is it more efficient to call an accessor method several times or to declare a temporary variable?

本文关键字:变量 是否 有效 声明 调用 访问 方法      更新时间:2023-10-16

假设我有一些代码多次调用vector::length()这样的方法。。。是否创建像这样的临时变量

int length=myVector.length()

使它比多次调用该方法更有效率?

这是一个有点假设性的问题,所以让我们假设调用vector::length()是获得所需结果的唯一方法。

在局部变量中存储值的成本几乎为零。调用内联的"获取此成员变量"的成本也几乎为零。

另一方面,如果对象不是向量,并且length不保存在成员变量中,而是必须计数——比如说像strlen()一样,那么将其存储在局部变量中会有很大的好处。特别是当字符串长度超过几个字符时。

另一个问题当然是你做了一些类似的事情:

int number_of_widgets = my_widgets.length();
...   // more code here, but none that affect my_widgets. 
last_widget = my_widgets[number_of_widgets-1]; 
... 

然后其他人去编辑cdoe:

int number_of_widgets = my_widgets.length();
... some code.
my_widgets.erase(some_widget_iterator);
...   // more code here
last_widget = my_widgets[number_of_widgets-1]; 
... 

现在您的代码访问超出了有效范围,可能会崩溃和烧录。。。

一如既往,细节是魔鬼。如果你想知道你的代码中什么是最快的,那么就用你的代码来进行基准测试。。。

在这种情况下,您不需要担心速度,直接调用length()很快。为了可读性,除非你真的多次调用它,否则我会说——直接调用它。如果它确实让代码变得丑陋,例如在10行上调用了10次,那么你可以将它缓存在一个变量中,使代码看起来更好。

优化的第一条规则:不要优化。反正它很快。我不认为vector::length()会减慢程序的速度,但无论如何,只要你没有速度问题,就没有充分的理由尝试手动优化它。如果相关,智能编译器应该决定并优化它。

在IDE上,你可以完成代码,所以这甚至不是输入更多的问题,只是代码的视觉可读性(同样,除非这个特定的函数会减慢程序的速度,我对此表示怀疑)。

唯一可以确定的方法是评测代码。

就我个人而言,如果我知道矢量在当前范围内不会改变,我会在最初优化可读性,并在需要时根据分析进行任何调整

const int number_of_widgets = myVector.size();

"我们应该忘记小效率,比如说97%的时间:过早优化是万恶之源"--唐纳德·克努思

真正的答案是,如果可以的话,你应该使用迭代器,因为它们通常更快,而且完全避免了这个问题(假设向量没有重新分配)。

你可能正在寻找的答案是:它通常在简单的情况下进行优化,但并不总是如此。

我假设它们将被编译为相同的代码。然而,假设是不好的,所以我尝试了一个测试程序。我第一次编译:

#include <iostream>
#include <vector>
int main()
{
    int myints[] = {16,2,77,29};
    std::vector<int> myVector (myints, myints + sizeof(myints) / sizeof(int) );
    int length=myVector.size();
    std::cout << length << std::endl;
    std::cout << length*3 << std::endl;
    return 0;
}

这正确地给出了4和12的输出。然后我尝试了这个程序,其中我不使用变量"长度"。

#include <iostream>
#include <vector>
int main()
{
    int myints[] = {16,2,77,29};
    std::vector<int> myVector (myints, myints + sizeof(myints) / sizeof(int) );
    std::cout << myVector.size() << std::endl;
    std::cout << myVector.size()*3 << std::endl;
    return 0;
}

这个程序也正确地给出了4和12的输出,并且做了完全相同的事情,但没有中间的可变长度。我可以声明,使用编译标志-O3或-O2,它们给出完全相同的二进制代码。这是用gcc编译器完成的。所以这两种方式都不快,而且它们使用的内存量相同。

因此,只要使用看起来最好、最容易阅读的即可。

尽管我不确定我们是否可以从我的测试中完全概括,因为可能还有其他优化在起作用。例如,myVector.size()在编译时被计算为4,因此可能已经硬编码到文件中,而不是在运行时计算出来。这会让我的测试变得毫无意义。

希望这能有所帮助。(虽然我在写这篇文章的时候看到了其他4个答案),所以其他人可能已经在测试这篇文章方面做得更好了。