20

想象一下以下声明:

void foo(){
    const std::array<int, 80000> arr = {/* a lot of different values*/};
    //do stuff
}

第二个:

void foo(){
    static const std::array<int, 80000> arr = {/* a lot of different values*/};
    //do stuff
}

如果有的话,这两者之间可能的性能差异是什么?这些解决方案是否存在任何危险?

4

4 回答 4

16

暂时忘记数组。这混淆了两个不同的问题。您已经得到了解决生命周期和存储问题的答案。我将解决初始化问题。

void f() {
    static const int x = get_x();
    // do something with x
}

void g() {
    const int x = get_x();
    // do something with x
}

这两者的区别在于,第一个只会get_x()在第一次被调用时f()调用;x在程序的其余部分保留该值。get_x()每次调用时,第二个都会调用g()

get_x()如果在后续调用中返回不同的值,这很重要:

int current_x = 0;
int get_x() { return current_x++; }
于 2019-03-01T13:00:18.820 回答
13

这些解决方案是否存在任何危险?

非静态是危险的,因为数组很大,而为自动存储保留的内存是有限的。根据系统和配置,该阵列可以使用大约 30% 的自动存储可用空间。因此,它大大增加了堆栈溢出的可能性。

虽然优化器肯定会避免在堆栈上分配内存,但您有充分的理由希望您的非优化调试版本也不会崩溃。

于 2019-03-01T10:53:38.400 回答
6

如果有的话,这两者之间可能的性能差异是什么?这些解决方案是否存在任何危险?

差异完全取决于您如何使用foo().

第一种情况:(低概率):您的实现是这样的,您只会调用foo()一次,也许您已经创建了单独的函数来按照实践划分代码逻辑。那么在这种情况下,声明为静态是非常糟糕的,因为静态变量或对象会一直保留在内存中,直到程序结束。所以想象一下你的变量不必要地占用内存。

第二种情况:(高概率):您的实现方式是您将foo()一次又一次地调用。然后非静态对象将被一次又一次地分配和取消分配。这将占用大量的 CPU 时钟周期,这是不希望的。在这种情况下使用静态。

于 2019-03-01T11:15:31.960 回答
3

在这个特定的上下文中,关于static在变量上使用初始化时要考虑的一点:

从 C++17 标准:

6.7.1 静态存储时长[basic.stc.static]
...
2如果一个具有静态存储时长的变量有初始化或有副作用的析构函数,即使它看起来没有被使用也不应该被淘汰,除了一个类可以按照 15.8 中的规定消除对象或其复制/移动。

于 2019-03-01T11:49:10.910 回答