小编典典

static 关键字及其在 C++ 中的各种用途

all

该关键字static在 C++ 中具有多种含义,我觉得这很令人困惑,我永远无法思考它实际上应该如何工作。

据我了解,有static存储持续时间,这意味着在全局情况下它会持续整个程序的生命周期,但是当您谈论本地时,这意味着它默认为零初始化。

C++ 标准对带有关键字的类数据成员这么说static

3.7.1 静态存储时长[basic.stc.static]

3 关键字 static 可用于声明具有静态存储持续时间的局部变量。

4 在类定义中应用于类数据成员的关键字 static 给出了数据成员静态存储的持续时间。

局部变量 是什么意思?那是一个函数局部变量吗?因为还有当你声明一个本地函数时static,它只初始化一次,第一次进入这个函数。

它也只讨论了关于类成员的存储持续时间,它不是特定于实例的,这也是一个static否的属性?或者是存储时间?

那么static文件范围的情况呢?默认情况下是否所有全局变量都被认为具有静态存储持续时间?以下(来自第 3.7.1 节)似乎表明了这一点:

1 所有没有动态存储时长、没有线程存储时长、 非本地 变量都有静态存储时长。这些实体的存储应持续整个程序(3.6.2、3.6.3)

static变量的链接有何关系?

这整个static关键字是彻头彻尾的混乱,有人可以澄清它英语的不同用途,还告诉我 什么时候 初始化一个static类成员?


阅读 136

收藏
2022-05-13

共1个答案

小编典典

变量:

static 变量存在于定义它的翻译单元 的“生命周期”中,并且:

  • 如果它在命名空间范围内(即在函数和类之外),则不能从任何其他翻译单元访问它。这称为“内部链接”或“静态存储持续时间”。(不要在标题中这样做,除了constexpr. 其他任何东西,你最终会在每个翻译单元中得到一个单独的变量,这非常令人困惑)
  • 如果它 是函数中 的变量,则不能从函数外部访问它,就像任何其他局部变量一样。(这是他们提到的当地人)
  • 由于 ,类成员没有限制范围static,但可以从类以及实例(如std::string::npos)中寻址。[注意:你可以在类中 声明 静态成员,但它们通常仍应在翻译单元(cpp 文件)中 定义 ,因此,每个类只有一个]

位置作为代码:

static std::string namespaceScope = "Hello";
void foo() {
    static std::string functionScope= "World";
}
struct A {
   static std::string classScope = "!";
};

在执行翻译单元中的任何函数之前(可能在main开始执行之后),该翻译单元中具有静态存储持续时间(命名空间范围)的变量将被“常量初始化”(constexpr在可能的情况下,否则为零),然后非本地人
按照它们在翻译单元中定义的顺序std::string="HI";正确地“动态初始化”(对于那些不是
这样的事情constexpr)。最后,函数局部静态将在第一次执行“到达”声明它们的行时被初始化。所有static变量都以初始化的相反顺序销毁。

获得这一切的最简单方法是将所有未constexpr初始化的静态变量设置为函数静态局部变量,这样可以确保在您尝试使用它们时正确初始化所有静态变量/全局变量,从而防止静态初始化命令惨败。

T& get_global() {
    static T global = initial_value();
    return global;
}

小心,因为当规范说命名空间范围变量默认具有“静态存储持续时间”时,它们的意思是“翻译单元的生命周期”位,但这并不 意味着 它不能在文件之外访问。

职能

明显更直接,static通常用作类成员函数,很少用于独立函数。

静态成员函数与常规成员函数的不同之处在于它可以在没有类实例的情况下调用,并且由于它没有实例,因此它不能访问类的非静态成员。当您希望为绝对不引用任何实例成员的类或管理static成员变量提供函数时,静态变量很有用。

struct A {
    A() {++A_count;}
    A(const A&) {++A_count;}
    A(A&&) {++A_count;}
    ~A() {--A_count;}

    static int get_count() {return A_count;}
private:
    static int A_count;
}

int main() {
    A var;

    int c0 = var.get_count(); //some compilers give a warning, but it's ok.
    int c1 = A::get_count(); //normal way
}

自由函数意味着该static函数不会被任何其他翻译单元引用,因此链接器可以完全忽略它。这有几个目的:

  • 可以在 cpp 文件中使用,以保证该函数永远不会从任何其他文件中使用。
  • 可以放在标题中,每个文件都有自己的函数副本。没用,因为 inline 做的事情几乎一样。
  • 通过减少工作来加快链接时间
  • 可以在每个翻译单元中放置一个同名的函数,它们都可以做不同的事情。例如,您可以static void log(const char*) {}在每个 cpp 文件中放置一个,并且它们都可以以不同的方式登录。
2022-05-13