static 关键字及其在 C++ 中的各种用途 [英] The static keyword and its various uses in C++

查看:33
本文介绍了static 关键字及其在 C++ 中的各种用途的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关键字 static 在 C++ 中具有多种含义,我觉得这很令人困惑,而且我永远不会考虑它实际应该如何工作.

The keyword static is one which has several meanings in C++ that I find very confusing and I can never bend my mind around how its actually supposed to work.

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

From what I understand there is static storage duration, which means that it lasts for the lifetime of the program in the case of a global, but when you're talking about a local, it means that it's zero initialized by default.

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

The C++ Standard says this for class data members with the keyword static:

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

3 关键字 static 可用于声明具有静态存储期的局部变量.

3 The keyword static can be used to declare a local variable with static storage duration.

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

4 The keyword static applied to a class data member in a class definition gives the data member static storage duration.

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

What does it mean with local variable? Is that a function local variable? Because there's also that when you declare a function local as static that it is only initialized once, the first time it enters this function.

它也只讨论了关于类成员的存储持续时间,它是非实例特定的,那也是 static 的一个属性,不是吗?还是那个存储期限?

It also only talks about storage duration with regards to class members, what about it being non instance specific, that's also a property of static no? Or is that storage duration?

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

Now what about the case with static and file scope? Are all global variables considered to have static storage duration by default? The following (from section 3.7.1) seems to indicate so:

1 所有没有动态存储期、没有线程存储期和非本地的变量都有静态存储期.这些实体的存储应在程序期间持续(3.6.2、3.6.3)

1 All variables which do not have dynamic storage duration, do not have thread storage duration, and are not local have static storage duration. The storage for these entities shall last for the duration of the program (3.6.2, 3.6.3)

static 与变量的链接有何关系?

How does static relate to the linkage of a variable?

这整个 static 关键字是彻头彻尾的混乱,有人可以澄清它的不同用途英语并告诉我 何时 初始化 static班级成员?

This whole static keyword is downright confusing, can someone clarify the different uses for it English and also tell me when to initialize a static class member?

推荐答案

变量:

static 变量存在于生命周期"中中定义的翻译单元,以及:

Variables:

static variables exist for the "lifetime" of the translation unit that it's defined in, and:

  • 如果它在命名空间范围内(即在函数和类之外),则不能从任何其他翻译单元访问.这被称为内部链接".或静态存储持续时间".(不要在标题中这样做,除了 constexpr.其他任何东西,你都会在每个翻译单元中得到一个单独的变量,这很令人困惑)
  • 如果它是一个函数中的变量,就不能从函数外部访问它,就像任何其他局部变量一样.(这是他们提到的当地)
  • 由于static,类成员没有限制范围,但可以从类和实例(如std::string::npos)寻址.[注意:您可以在类中声明静态成员,但它们通常仍应定义在翻译单元(cpp文件)中,因此,每个班级]
  • If it's in a namespace scope (i.e. outside of functions and classes), then it can't be accessed from any other translation unit. This is known as "internal linkage" or "static storage duration". (Don't do this in headers except for constexpr. Anything else, and you end up with a separate variable in each translation unit, which is crazy confusing)
  • If it's a variable in a function, it can't be accessed from outside of the function, just like any other local variable. (this is the local they mentioned)
  • class members have no restricted scope due to static, but can be addressed from the class as well as an instance (like std::string::npos). [Note: you can declare static members in a class, but they should usually still be defined in a translation unit (cpp file), and as such, there's only one per class]

位置即代码:

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变量都按照初始化相反的顺序销毁.

Before any function in a translation unit is executed (possibly after main began execution), the variables with static storage duration (namespace scope) in that translation unit will be "constant initialized" (to constexpr where possible, or zero otherwise), and then non-locals are "dynamically initialized" properly in the order they are defined in the translation unit (for things like std::string="HI"; that aren't constexpr). Finally, function-local statics will be initialized the first time execution "reaches" the line where they are declared. All static variables all destroyed in the reverse order of initialization.

使这一切正确的最简单方法是将所有不是 constexpr 初始化的静态变量初始化为函数静态局部变量,这确保在您尝试执行时正确初始化所有静态变量/全局变量无论如何都要使用它们,从而防止静态初始化顺序失败.

The easiest way to get all this right is to make all static variables that are not constexpr initialized into function static locals, which makes sure all of your statics/globals are initialized properly when you try to use them no matter what, thus preventing the static initialization order fiasco.

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

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

Be careful, because when the spec says namespace-scope variables have "static storage duration" by default, they mean the "lifetime of the translation unit" bit, but that does not mean it can't be accessed outside of the file.

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

Significantly more straightforward, static is often used as a class member function, and only very rarely used for a free-standing function.

静态成员函数与普通成员函数的不同之处在于它可以在没有类的实例的情况下被调用,并且由于它没有实例,它不能访问类的非静态成员.当您想要为绝对不引用任何实例成员的类或管理 static 成员变量的类提供一个函数时,静态变量非常有用.

A static member function differs from a regular member function in that it can be called without an instance of a class, and since it has no instance, it cannot access non-static members of the class. Static variables are useful when you want to have a function for a class that definitely absolutely does not refer to any instance members, or for managing static member variables.

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 自由函数意味着该函数不会被任何其他翻译单元引用,因此链接器可以完全忽略它.这有几个目的:

A static free-function means that the function will not be referred to by any other translation unit, and thus the linker can ignore it entirely. This has a small number of purposes:

  • 可以在 cpp 文件中使用,以保证该函数不会在任何其他文件中使用.
  • 可以放在头文件中,每个文件都有自己的函数副本.没有用,因为内联几乎可以做同样的事情.
  • 通过减少工作来加快链接时间
  • 可以在每个翻译单元中放置一个同名的函数,它们都可以做不同的事情.例如,您可以在每个 cpp 文件中放置一个 static void log(const char*) {},它们都可以以不同的方式记录.
  • Can be used in a cpp file to guarantee that the function is never used from any other file.
  • Can be put in a header and every file will have it's own copy of the function. Not useful, since inline does pretty much the same thing.
  • Speeds up link time by reducing work
  • Can put a function with the same name in each translation unit, and they can all do different things. For instance, you could put a static void log(const char*) {} in each cpp file, and they could each all log in a different way.

这篇关于static 关键字及其在 C++ 中的各种用途的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆