0

编辑:我知道在循环体之前声明一个对象更有效,因为它在每次函数调用时调用构造函数和析构函数,而不是每次循环迭代一次。假设由于这种推理,类型 A 的对象在循环体之外更有效。

我想知道如果以下

void foo()
{
    static A var;  //A is a class with a constructor
    ...   //stuff done with var
}

void foo()
{
    A var;   //A is a class with a constructor
    ...  //stuff done with var
}

因为前者会调用 A 的构造函数和析构函数一次,而不是后者每次调用 foo 时都会调用它。我通常在所有本地对象中问这个问题。

4

3 回答 3

1

先做对,再做快。带有静态变量的版本会继承上一次调用的值;除非您需要在多次调用中保留信息,否则良好的设计要求将变量设置为已知状态,这就是构造函数所做的。如果你不使用构造函数,也就是说,你将变量设为静态,那么你必须做一些其他的事情来让变量进入一个已知的状态;也就是说,您最终调用了一个函数,该函数执行构造函数会执行的操作,但是您的语法更加晦涩难懂。

这是一个有点过于简单的例子:

void f(int j) {
    static int i = 0;
    i = 0; // reset, because previous call left i with some spurious value
    while (i < j)
        std::cout << i << '\n';
}

除此之外,在调用之间共享该变量意味着在多线程程序中,您必须同步对该函数的所有调用,从而引入一个瓶颈,该瓶颈几乎肯定会抵消每次使用时不构造对象所带来的任何性能提升。

于 2013-08-17T13:19:35.293 回答
1

首先,它在语义上是不同的。你在比较两个不同的东西。如果您不关心语义差异,则任何一个都可以比另一个更快。如果 的构造A没有做太多,例如,仅初始化 an int,那么第二个版本很可能更快,例如,因为编译器需要知道它是否var在运行时初始化,而在 C++11 中,初始化是线程-安全的。如果A有些涉及到的构造,则第一个版本可能更快。

找出任何给定应用程序的唯一方法是测量。

于 2013-08-16T23:43:05.843 回答
1

经验法则:按您的意思编码(本地对象还是逻辑上需要在每次调用时共享?)并让编译器担心优化。

我对非平凡类型的常量例外。例如,'static const std::string' 比 'const std::string' 更好,因为它每次都保存动态分配。但是,如果对象不包含动态分配并且它的大小不是几十个字节,则将其设为局部变量。

出于效率原因,无需将基本类型(例如const intor const char *const)设为静态,尽管这不会造成伤害。

由于静态对象在线程之间共享,编译器可能需要在每次需要使用它时检查它是否没有被另一个线程更新,而对于局部变量则不能这样。所以不要假设静态将是“最快的”。(其工作原理取决于您的编译器实现)

当然,您还需要了解是否将其设为静态可能会改变程序的行为。我上面的信息假设选择不会。

于 2013-08-17T02:05:32.933 回答