5

这是我之前的问题范围的扩展。

究竟什么是“静态”,它是如何使用的,在处理 C++ 时使用“静态”的目的是什么?

谢谢。

4

6 回答 6

13

这意味着该变量对于翻译单元是本地的(简单地说,对于单个源文件),并且不能从其外部访问。这种使用 static 实际上在当前的 C++ 标准中已被弃用 - 相反,您应该使用匿名命名空间:

static int x = 0;    

应该:

namespace {
    int x = 0;    
}
于 2010-08-05T16:08:32.823 回答
10

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

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

// test.cpp
static int a = 1;
static void foo() {}

如果编译该翻译单元的结果与包含符号的不同翻译单元链接,a并且foo它不会违反单一定义规则,如在此特定翻译单元中a并且foo私有符号。这种用法已被未命名的命名空间淘汰。

// test2.cpp
namespace {
   static int a = 1;
   static void foo() {}
}

在函数中声明局部变量时,这意味着变量的生命周期将从第一次调用函数到程序结束,而不仅仅是在调用期间:

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

在前面的代码中,第一次调用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
}

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

这种使用static类似于 Java 中使用相同的关键字,而其他两个在该语言中不存在。Java 中有一个关键字在 C++ 中不存在,即使用静态类初始化器(类级别的代码块,由 包围static { ... })。在 Java 中,该代码块将在加载类时执行一次,并且只执行一次。C++中静态成员变量的初始化必须在变量定义的初始化器中完成。

于 2010-08-05T17:33:12.530 回答
6

这些东西似乎在这里得到了很好的介绍。

但解释一下,C 中有 2 个用途

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

    int getNextId() { 静态 int id = 0; 返回 id++; }

C++ 继承了这两者,并添加了自己的两个用途。

  1. 静态成员变量:跨类的所有实例“共享”的变量,也可以在不引用类实例的情况下进行访问。Shared 似乎是一个错误的词,但本质上我相信结果是任何对静态成员变量的引用都引用了相同的内存位置。
  2. 静态方法:可以在不引用定义它的类的特定实例的情况下调用的方法。
于 2010-08-05T16:28:54.897 回答
2

静态基本上意味着变量与程序的生命周期相关,而不是任何给定的函数或类实例。你应该什么时候使用它?不。什么目的?主要是调试数据。

通常,在 C++ 中,如果您发现自己使用静态数据,那么您就做错了。有时它是合适的,但它们非常罕见。

于 2010-08-05T16:15:35.433 回答
1

当在 C++ 中的类中使用 static 时,它的含义或多或少与 Java 中的相同。对于变量,这意味着所有类都存在一个变量实例,对于函数,这意味着函数根本不会隐式访问 this 指针。

在 C 和 C++ 中,当静态用于全局变量或函数时,这意味着该变量只能在当前 C 或 C++ 文件中被引用。换句话说,编译器不得为变量或函数生成任何重定位符号。

当在局部函数中的变量旁边使用静态时,这意味着该变量不会超出范围,但会在函数调用到函数调用时保留其值。该变量实际上成为一个只能从给定函数访问的全局变量。

于 2010-08-05T16:30:14.957 回答
0

静态类成员是与类本身相关联的数据和函数,而不是与类的对象相关联。

在下面的示例中,Fred 类有一个静态数据成员 x_ 和一个实例数据成员 y_。无论创建了多少 Fred 对象(包括没有 Fred 对象),Fred::x_ 都只有一份副本,但每个 Fred 对象都有一个 y_。因此,x_ 被称为与类相关联,而 y_ 被称为与类的单个对象相关联。类似地,Fred 类有一个静态成员函数 f() 和一个实例成员函数 g()。

class Fred {
    public:
        static void f() throw();                           <-- 1
        void g() throw();                                  <-- 2
    protected:
        static int x_;                                     <-- 3
        int y_;                                            <-- 4
};

(1) 与类关联的成员函数

(2) 与类的单个对象关联的成员函数

(3) 与类关联的数据成员

(4) 与类的单个对象关联的数据成员

用法:

当您想了解创建的类的实例数量时,您可以使用静态变量。例如,在“Car”类中,每个 Car 实例可能有一个唯一的序列号(在这种情况下为 _y),公司可能希望跟踪生产的汽车数量(在这种情况下为 _x)。

于 2010-08-05T16:29:50.113 回答