C++ static关键字



C++ 中的static静态关键字

static 是 C++ 中的一个关键字,它可以让使用它的元素变得很“特别”,静态元素存储在静态存储区域中,它的生命周期在整个程序中仅分配一次,静态关键字可以与以下一起使用:

  1. 函数中的静态变量
  2. 静态类对象
  3. 类中的静态成员变量
  4. 类中的静态方法


函数内部的静态变量

函数 中使用的静态变量只初始化一次,即使函数多次被调用,它的值在上一次使用完后保存在静态区没有改变,更不会被重新初始化。

静态变量存储在静态存储区,而不是堆栈中。

void counter()
{
    static int count=0;
    cout << count++;
}

int main(0
{
    for(int i=0;i<5;i++)
    {
        counter();
    }
}

以上实例输出结果:

0 1 2 3 4

让我们在不使用静态变量的情况下查看相同程序的输出。

void counter()
{
    int count=0;
    cout << count++;
}

int main(0
{
    for(int i=0;i<5;i++)
    {
        counter();
    }
}

以上实例输出结果:

0 0 0 0 0

如果我们不使用 static 关键字,变量 count 会在每次调用 counter() 函数时重新初始化,并在每次 counter() 函数结束。但是,如果我们将其设为静态,则一旦初始化 count 将具有一个作用域,直到整个程序结束,它都不会再次初始化。

如果你不初始化静态变量,它们默认值为零。



静态类对象

对于 类对象,static静态关键字的工作方式也相同。声明为静态的对象在静态存储区中分配存储,一直到程序结束。

静态对象也像其他普通对象一样使用 构造函数 进行初始化,并将类中的成员变量初始化为0,使用 static 关键字仅适用于 原始数据类型,而不适用于 用户自定义的数据类型

class Abc
{
    int i;
public:
    Abc()
    {
        i=0;
        cout << "构造函数";
    }
    ~Abc()
    {
        cout << "析构函数";
    }
};

void f()
{
    static Abc obj;
}

int main()
{
    int x=0;
    if(x==0)
    {
        f();
    }
    cout << "END";
}

以上实例输出结果:

构造函数 END 析构函数

你一定在想,为什么在 if 条件的作用域结束时没有调用析构函数,对象 obj 应该被销毁。这是因为对象是 static,它的生命周期一直到程序结束,因此当 main() 函数退出时,才会调用该对象的析构函数。



类中的静态数据成员

类的静态数据成员是所有对象共享的成员,静态数据成员存储在程序的静态区,所有该类的对象都可以使用,它不能像非静态数据成员一样作为每个对象的单独副本使用。

静态成员变量(数据成员)不使用构造函数初始化,因为它们不依赖于对象的初始化。

此外,它必须显式初始化,始终在类之外。如果没有初始化,编译器会报错。

class X
{
public:
    static int i;
    X()
    {
        // 构造函数
    };
};

int X::i=1;

int main()
{
    X obj;
    cout << obj.i;   // 输出 i 的值
}

以上实例输出结果:

1

一旦定义了 static 数据成员,就不能再次定义它。但是,可以对其执行算术运算。



静态成员函数

静态成员函对整个类起作用,而不是对类的某个特定对象起作用。

可以使用对象直接使用 . 运算符来调用它。但是,一般我们使用类名和作用域解析 :: 运算符来调用静态成员函数。

例如:

class X
{
    public:
    static void f()
    {
        // 
    }
};

int main()
{
    X::f();   // 通过类名直接调用静态成员函数
}

这些函数不能访问普通的数据成员和成员函数,只能访问静态数据成员和静态成员函数

它没有任何“this”关键字,这就是它无法访问普通成员的原因,后面章节中我们将研究“this”关键字。