成员函数中的静态变量

mon*_*nik 151 c++ static scope

有人可以解释成员函数中的静态变量如何在C++中工作.

鉴于以下课程:

class A {
   void foo() {
      static int i;
      i++;
   }
}
Run Code Online (Sandbox Code Playgroud)

如果我声明了多个实例A,那么调用foo()一个实例会增加i所有实例上的静态变量吗?或者只是它被召唤的那个?

我假设每个实例都有自己的副本i,但是通过一些代码,我似乎另有说明.

iam*_*ind 159

由于class A是非模板类,A::foo()因此是非模板函数.static int i程序内只有一个副本.

A对象的任何实例都会影响相同,i并且i整个程序将保留生命周期.要添加示例:

A o1, o2, o3;
o1.foo(); // i = 1
o2.foo(); // i = 2
o3.foo(); // i = 3
o1.foo(); // i = 4
Run Code Online (Sandbox Code Playgroud)

  • 虽然这可能不是您正在寻找的样式,但是使用A类的私有数据成员会产生您所描述的效果.如果您担心名称冲突,可以添加一个前缀,例如`m_`来指示i的状态. (13认同)
  • 谢谢你的好榜样!是否有办法实际实现某些特定于实例的静态int i的范围,例如`o1.foo(); // i = 1`和`$ o2.foo(); // i = 1` ......? (3认同)
  • 请提及如果类和方法被模板化会发生什么。 (3认同)
  • @ytobi,在这种情况下,对于普通/模板类的模板化方法的每个实例,将创建一个单独的静态变量。该变量仅适用于这些类型。例如 `template<typename T> void foo (T t) {...}`。现在,对于“foo<int>”,将有一个“static int i”(例如“foo<int>::i”),对于“foo<string>”,将有一个单独的“static int i”(例如`foo<string>::i`) 等等。`foo<int>` 的 `i` 将单独递增,而不是 `foo<string>` 的递增。希望能消除疑虑。 (3认同)
  • @Andrew你提出了一个重要的观点。它已经被语言开发者实现了。编译器将此类零初始化变量放置在 .bss 段中。来自https://en.cppreference.com/w/cpp/language/initialization:要进行零初始化的变量放置在程序映像的.bss段中,该段不占用磁盘空间,并被操作系统清零加载程序时。 (2认同)

650*_*502 131

static不幸的是,关键字在C++中有一些不同的无关含义

  1. 当用于数据成员时,它意味着数据在类中而不是在实例中分配.

  2. 当用于函数内部的数据时,意味着数据是静态分配的,在第一次进入块时初始化,并持续到程序退出.此变量仅在函数内部可见.局部静力学的这一特殊功能通常用于实现单身人士的懒惰建构.

  3. 当在编译单元级别(模块)使用时,它意味着变量就像一个全局变量(即mainmain退出之前运行和销毁之前分配和初始化)但是该变量在其他编译单元中不可访问或可见.

我强调了对每种用途最重要的部分.稍微不鼓励使用(3)支持未命名的命名空间,这些命名空间也允许未导出的类声明.

在您的代码中,static关键字与含义编号2一起使用,与类或实例无关......它是函数的变量,并且只有一个副本.

正如iammilind所说的那样,如果函数是模板函数,那么该变量可能有多个实例(因为在这种情况下,函数本身确实可以存在于程序中的许多不同副本中).即使在这种情况下,课程和实例也无关紧要......请参阅以下示例:

#include <stdio.h>

template<int num>
void bar()
{
    static int baz;
    printf("bar<%i>::baz = %i\n", num, baz++);
}

int main()
{
    bar<1>(); // Output will be 0
    bar<2>(); // Output will be 0
    bar<3>(); // Output will be 0
    bar<1>(); // Output will be 1
    bar<2>(); // Output will be 1
    bar<3>(); // Output will be 1
    bar<1>(); // Output will be 2
    bar<2>(); // Output will be 2
    bar<3>(); // Output will be 2
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,`关键字static的+1在C++中有一些不相关的含义`:) (38认同)
  • @austinmarton:在C++中不推荐使用"使用静态来表示'本地翻译单元'.在我的版本中使用C++编程语言(1999年9月第10版)中使用了未命名的命名空间(8.2.5.1)"在第819页. (3认同)

Sau*_*oot 5

函数内的静态变量

  • 静态变量是在函数内部创建的,存储在程序的静态内存中而不是堆栈中。

  • 静态变量初始化将在第一次调用函数时完成。

  • 静态变量将在多个函数调用中保留该值

  • 静态变量的生命周期是 Program

在此处输入图片说明

例子

#include <iostream>

using namespace std;

class CVariableTesting 
{
    public:
    
    void FuncWithStaticVariable();
    void FuncWithAutoVariable();

};

void CVariableTesting::FuncWithStaticVariable()
{
    static int staticVar = 0; //staticVar is initialised by 0 the first time
    cout<<"Variable Value : "<<staticVar<<endl;
    staticVar++;
}
void CVariableTesting::FuncWithAutoVariable()
{
    int autoVar = 0;
    cout<<"Variable Value : "<<autoVar<<endl;
    autoVar++;
}
    

int main()
{
    CVariableTesting objCVariableTesting;
    cout<<"Static Variable";
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    
    cout<<endl;
    cout<<"Auto Variable";
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出 :

静态变量

变量值:0
变量值:1
变量值:2
变量值:3
变量值:4

自动变量

变量值:0
变量值:0
变量值:0
变量值:0
变量值:0