成员静态函数中的C++静态变量

C++ static variable inside a member static function

本文关键字:静态 变量 C++ 静态函数 成员      更新时间:2023-10-16

通常,我想知道成员的static函数的局部变量存储在哪里?也就是说,如果static变量只在static函数内部使用,那么该变量是否只初始化过一次?

请参阅下面的代码

std::string const CONST1 = "const1";
std::string const CONST2 = "const2";
std::string const CONST3 = "const3";
class Test
{
  public:
    static const std::vector<std::string> GetSomeMap();
}
const std::vector<std::string> Test::GetSomeMap()
{
  static std::vector<std::string> SomeMap = boost::assign::list_of(CONST1)(CONST2)(CONST3);
  
  return SomeMap;
}

对于上面的代码,将SomeMap声明为static有好处吗?(我希望它只初始化一次。)

如果在静态函数中使用静态变量,该变量是否只初始化过一次?

答案是肯定的
对于正则(即非static)成员函数的static变量也是"是"
对于非成员函数的static变量也是"是"。

函数内部的静态变量(无论函数类型如何)与全局变量一样存储在"DATA"段中。所以你可以说,通过这种方式,函数静态变量与全局变量相似,只是它们只能在有限的范围内(函数体)通过名称访问。

如果变量是静态的,则将其存储在堆中。如果一个变量是静态函数的成员,则它存储在静态局部变量中。而且,它们只初始化一次。

一般来说,我想问一个成员静态函数的局部变量存储在哪里?

取决于。静态常量纯旧数据类型可以存储在只读数据段中。具有常数初始化器的静态变量可以存储在数据段中,并且需要动态初始化的静态变量可存储在BSS段中。

如果在静态函数中使用静态变量,该变量是否只初始化过一次?

是的。在这种情况下,SomeMap将在控件第一次通过其声明时初始化。

在任何进行其他初始化。POD类型(3.9)的本地对象,静态存储持续时间初始化为常量表达式在第一次输入其块之前进行初始化。允许执行在与允许实现在命名空间范围内静态初始化具有静态存储持续时间的对象(3.6.2)。否则,当控件第一次通过其声明时,该对象被初始化;这样的对象在完成初始化时被视为已初始化。如果初始化通过抛出退出异常,初始化未完成,因此下次控件进入时将重试公告

ISO/IEC 14882:2003(E)第6.7节第4段(对不起,我手边没有该标准的最新副本)

从上面的代码来看,将SomeMap声明为静态是否有好处?(我希望它只初始化一次)

是的,声明它为静态有一个好处——它只会初始化一次,并且只有在使用时才会初始化。如果从未调用Test::GetSomeMap,则SomeMap从未初始化。

然而,正如@Blacktempel在上面所说,Test::GetSomeMap应该通过引用返回,以消除对创建额外副本SomeMap的任何疑问。

您还应该注意,创建三个字符串(CONST1、CONST2和CONST3)会产生成本,每个字符串都可能分配堆内存来存储其常量表达式字符串初始值设定项("CONST1"、"CONST2"answers"CONST3")的副本。此外,如果您调用Test::GetSomeMap,您还将承担初始化SomeMap向量的成本,该向量还可能分配堆内存来存储字符串的副本。

如果您关心内存使用和初始化开销,并且确实想要一个静态常量字符串数组,那么只需声明一个,如下所示:

   static const char* const * GetSomeMap(void) {
    static const char* const SomeMap[] = {"const1", "const2", "const3"};
    return SomeMap;
}

SomeMap将在没有初始化开销的情况下消耗最少的内存(并且是完全不可更改的)。