【问题标题】:Do I need to declare arrays as static local variables?我需要将数组声明为静态局部变量吗?
【发布时间】:2019-01-24 16:21:17
【问题描述】:

假设我有一个我经常调用的函数,其中有一个数组:

char foo[LENGTH];

根据LENGTH 的值,每次调用函数时分配这可能会很昂贵。我见过:

static char foo[LENGTH];

所以它只分配一次并且始终使用该数组:https://en.cppreference.com/w/cpp/language/storage_duration#Static_local_variables

这是数组的最佳做法吗?

编辑:

我已经看到几个回答说静态本地人不是最好的。但是初始化成本呢?如果我打电话怎么办:

char foo[LENGTH] = "lorem ipsum";

不是每次调用函数时都要复制吗?

【问题讨论】:

  • 对移动球门柱投反对票。
  • @Bathsheba 我的拉丁文是星期。可以翻译一下吗?
  • @JonathanMee 关于您的编辑,如果您想在函数中修改 foo ,则无论如何都必须手动重置它,否则它可能仍然具有上一次迭代的修改内容。我认为这是不可取的,因为如果它是可取的,您将不得不从一开始就使用 static 并且毫无疑问。如果您不想修改 foo ,则可以改用 const char * foo 。无论哪种情况,静态都无济于事。
  • 请注意,您的编辑使已经提供的 4 个回答原始问题的答案无效。
  • 不需要道歉。只需接受此问题的一个答案,还原您的更改并提出新的问题。

标签: c++ arrays variables static allocation


【解决方案1】:

由于 LENGTH 应该是一个编译时间常数(C++,没有 C99 VLA),foo 只会使用堆栈上的空间。非常快。

【讨论】:

  • 很抱歉,我已经稍微移动了目标帖子...但是初始化呢?这会改变我们的偏好吗?
  • 您应该针对这个具体案例提出问题,因为这将是一个完全不同的答案(请参阅godbolt.org/z/Kaia8H)。
【解决方案2】:

首先,分配 char 自动数组的时间不依赖于它的大小,并且在任何理智的实现中都是递增堆栈指针的恒定时间复杂度,这是超快的。请注意,即使对于 VLA(在 C++ 中无效)也是如此,只是该增量将是运行时操作数。另请注意,如果您的数组被初始化,答案会有所不同。

所以目前还不清楚您指的是什么性能缺陷。

另一方面,如果您创建上述数组static,则在提供的示例中您不会受到任何惩罚 - 因为 char 没有初始化,所以不会有正常的同步,这会阻止静态变量被双重初始化。但是,您的函数将(可能)成为线程不安全的。

底线:过早优化是万恶之源。

【讨论】:

  • 是的,我确实在询问后移动了目标帖子:(我实际上想知道 with 初始化,使用静态局部变量有意义吗?
  • 不需要道歉。只需接受此问题的一个答案,还原您的更改并提出新的问题。
【解决方案3】:

“分配”原始数据类型的对象并具有自动存储持续时间通常不是什么大问题。问题更多:您是否希望foo 的内容在函数执行后仍然存在?

例如,考虑以下函数:

char* bar() {
   char foo[LENGTH];
   strcpy(foo, "Hello!");
   return foo;  // returning a pointer to a local variable; undefined behaviour if someone will use it.
}

在这种情况下,foo 将超出范围,并且在 bar 完成后将无法(合法)访问。

一切都好,但是,如果你写

char* bar() {
   static char foo[LENGTH];
   strcpy(foo, "Hello!");
   return foo;  // foo has static storage duration and will be destroyed at the end of your program (not at the end of bar())
}

如果变量变得如此之大以至于它们将超过(有限的)堆栈大小,或者如果您递归调用函数,则可能会出现自动存储持续时间的大变量问题。但是,要克服这个问题,您需要改用动态内存分配(即新建/删除)。

【讨论】:

  • 我认为尺寸不是问题。我相信编译器已经为我处理好了。如果它太大,它会处理把它放在堆上。
  • 不,编译器不会那样做。它将“在堆栈上”,当LENGTH 变大时,您会遇到问题(可能没有任何警告)。
  • @JonathanMee,不,不会。如果数组增长到超过允许的堆栈大小,您将......猜猜是什么...... STACK OVERFLOW
  • 然而,斯蒂芬错了。 static char foo[LENGTH]; 永远不会在堆栈上分配。如果有的话,答案应该是相反的——大型自动变量会带来堆栈溢出的风险,而静态变量则不会。
  • @SergeyA:对; “局部变量”是错误的术语;将其更正为“自动存储期限”。
猜你喜欢
  • 2011-08-16
  • 2019-06-12
  • 2015-02-17
  • 1970-01-01
  • 1970-01-01
  • 2013-10-13
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多