在C++中声明"全局"变量时,"静态"到底意味着什么?

Hri*_*sto 5 c++ static static-variables

这是我前一个问题范围的扩展.

什么是"静态",它是如何使用的,以及在处理C++时使用"静态"的目的是什么?

谢谢.

小智 13

这意味着变量是翻译单元的本地变量(简单地放到单个源文件中),并且不能从外部访问.事实上,在当前的C++标准中不推荐使用静态 - 而是应该使用匿名命名空间:

static int x = 0;    
Run Code Online (Sandbox Code Playgroud)

应该:

namespace {
    int x = 0;    
}
Run Code Online (Sandbox Code Playgroud)

  • 匿名命名空间的东西确实需要被人们击败.15年前有太多的C++程序员学习过C++,从那时起就没有学过任何东西. (2认同)
  • 从标准2 [lex]/1:"程序文本保存在本国际标准中称为源文件的单元中.源文件连同所有标题(17.4.1.2)和源文件包括(16.2)通过预处理指令#include,减少任何条件包含(16.1)预处理指令跳过的任何源行,称为转换单元.(即预处理后输入代码的结果)重要的一点是,如果在头文件中声明一个`static`,它将是包含它的每个转换单元中的不同var. (2认同)

Dav*_*eas 10

关键字static在C++中具有不同的含义,具体取决于上下文.

声明自由函数或全局变量时,意味着该函数不能在此单个翻译单元之外使用:

// test.cpp
static int a = 1;
static void foo() {}
Run Code Online (Sandbox Code Playgroud)

如果编译该翻译单元的结果与包含符号的不同翻译单元链接,a并且foo它不会破坏单定义规则,如在该特定翻译单元中a并且foo私有符号.这种用法已被未命名的命名空间废弃.

// test2.cpp
namespace {
   static int a = 1;
   static void foo() {}
}
Run Code Online (Sandbox Code Playgroud)

在函数中声明局部变量时,意味着变量的生命周期将从第一次调用函数扩展到函数的末尾,而不仅仅是在调用的持续时间内:

int foo() {
   static int counter = 0;
   return ++counter;
}
int main() {
  for ( int i = 0; i < 10; ++i ) { 
     std::cout << foo() << std::endl;
  }
}
Run Code Online (Sandbox Code Playgroud)

在前面的代码中,在第一次调用counter时初始化一次foo,但变量将比函数更长,并将值保持在不同的函数调用之间.之前的代码将打印"1 2 3 4 ... 10".如果未声明变量,static则输出将为"1 1 1 ... 1".

在类范围内,static表示该成员是该类的成员,而不是特定实例的成员.此用法等同于您在其他问题中的使用:该特定成员的使用不受任何特定对象的约束.

struct test {
   int x;
   static int y;
};
int test::y;       // need to define it in one translation unit
int main() {
   // test::x = 5; // !error cannot access a non-static member variable
                   // without an instance
   test::y = 5;    // ok
   test t, other;
   t.x = 10;       // ok
   t.y = 15;       // ok, the standard allows calling a static member through
                   // an instance, but this is the same as test::y
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,成员x是非静态成员属性,因此x每个类的实例都有不同的属性.在示例程序中t.xother.x引用不同的整数.在另一方面ystatic,因此存在的单个实例test::y在程序中.即使标准允许调用,t.y并且other.y两个用户都引用相同的变量.成员方法也是如此.如果它们是静态的,则它们是类级方法,可以在没有实例的情况下调用,而如果它们是非静态的,则它们应用于具体实例,并且必须使用a.ba->b语法.

这种使用static类似于在Java中使用相同的关键字,而其他两个在该语言中不存在.Java中有一个关键字在C++中没有使用,那就是使用静态类初始值设定项(包含在类级别的代码块static { ... }).在Java中,只有一次加载类时才会执行代码块.必须在变量定义的初始化程序中初始化C++中的静态成员变量.


tor*_*rak 6

这个东西似乎在这里得到了很好的报道.

但是要解释一下,C中有两种用法

  1. 防止在定义它的文件范围之外使用全局变量.
  2. 允许函数内的局部变量在函数的调用中持久存在,如

    int getNextId(){static int id = 0; return id ++; }

C++继承了这两者,并增加了它自己的两个用途.

  1. 静态成员变量:在所有类的实例中"共享"的变量,也可以在不引用类的实例的情况下进行访问.共享似乎是错误的单词,但实质上我相信结果是对静态成员变量的任何引用都引用相同的内存位置.
  2. 静态方法:可以在不引用定义它的类的特定实例的情况下调用的方法.