5

在文件中的块内和块外声明静态变量有什么区别?例如,在这里,静态变量 a、b、c、d 之间有什么区别?我们可以声明一个可以从程序的所有文件中访问的静态变量吗?

    static int a;
    void getVol(..)
    { 
       static int b;
    }

    int main()
    {
       static int c;
       while(condition)
       {
           static int d;
            ....
       }
    some code here;
    return 0;
    }
4

6 回答 6

13

最终,没有区别。忽略(暂时)静态成员函数,static意味着它的含义——但我们在不同的条件下看到它的不同部分,因为它的某些含义也可以在没有关键字的情况下发生。

当您使用static关键字时,被定义的对象始终具有:

  1. 静态生命周期——它存在于程序的整个生命周期。
  2. 本地可见性——名称在其声明的范围之外不可见。

无论是在块内部还是外部定义的静态变量,这两者都是正确的。默认情况下会发生其中的一部分,即使您不使用static关键字,但如果您使用关键字,您总是会得到两者。

static成员函数是类似的,但由于它们是函数,它们并不完全具有生命周期——所有函数都有静态生命周期。静态成员函数具有局部可见性(即,它的名称仅在其类中可见)和类似于“静态生命周期”的东西——该函数不绑定到类的实例。

对于那些关心初始化块级静态变量的具体时间的人,血腥细节如下(第 6.7/4 节):

具有静态存储持续时间 (3.7.1) 或线程存储持续时间 (3.7.2) 的所有块范围变量的零初始化 (8.5) 在任何其他初始化发生之前执行。如果适用,具有静态存储持续时间的块范围实体的常量初始化(3.6.2)在其块首次进入之前执行。

允许实现在与允许实现在命名空间范围(3.6.2)中静态初始化具有静态或线程存储持续时间的变量相同的条件下,对具有静态或线程存储持续时间的其他块范围变量执行早期初始化。否则,此类变量在控件第一次通过其声明时被初始化;这样的变量在其初始化完成时被认为已初始化。

因此,该变量将在程序启动的早期初始化为零。然后,如果已指定其他初始化,则不会迟于执行通过初始化时发生(但可能会更早发生)。但是,请注意常量初始化和其他初始化之间的区别。例如,考虑这样的事情:

int g()  { return 2; }

int f() { 
    goto bypass;

    static int x = 1;
    static int y = g();

bypass:

    std::cout << x << "\n" << y;
}

在这里,x是常量初始化,但y不是。由于x是常量初始化,它在进入块时被初始化,所以当我们打印出它的值时,我们应该得到1. y但是,它不是常量初始化的,并且 goto 意味着执行永远不会通过其初始化 - 因此,它将保留0在任何其他初始化发生之前它被初始化的那个,因此(使用正常运行的编译器)输出将是:

1 
0
于 2013-08-09T05:50:02.210 回答
1

块内的静态变量(局部静态变量) -

  1. 它在块/功能之外不可见
  2. 它的值保留在函数调用中,因为它是静态的

块外的静态变量(全局静态变量) -

  1. 它的范围是整个文件(就像你的程序中的一个)
  2. 它的值在函数调用之间保留,因为它是静态的。
于 2013-08-09T05:41:45.750 回答
1
static int a;

表示该变量a是文件范围变量,即不能从其他文件中看到。

void getVol(..)
 { 
   static int b;
 }

意味着局部变量b有一个从程序开始到程序结束的生命周期,也就是说,你可以给它赋值,而在下一次调用函数时,它会记住这个值。

c并且d类似于b

于 2013-08-09T05:34:36.247 回答
1

以下对我有用:

/*
 * How to create an object on the stack.
 * Also make sure that only 5 objects are created for the class
*/

#include <iostream>

using namespace std;

class User {
private:
    int id;
    static int counter;
    static bool isOk;
public:
    User();
    ~User() {}
    int getId() { return id; }
    static int getCounter() { return counter; }
    static bool getStatus() { return isOk; }
    static void resetOk() { isOk = false; }
    static void setOk() { isOk = true; }
};

User::User() {
    if(counter == 5) {
        cout << "Not allowed to create more than 5 objects" << endl;
        resetOk();
        return;
    }
    counter++;
    id = counter;
    setOk();
}

int User::counter = 0;
bool User::isOk = false;

int main()
{
    // Create objects on stack
    User user1;
    (User::getStatus()) ? cout << "user1 id: " << user1.getId() << endl :
                          cout << "Object Construction Failed" << endl;
    User user2;
    (User::getStatus()) ? cout << "user2 id: " << user2.getId() << endl :
                          cout << "Object Construction Failed" << endl;
    User user3;
    (User::getStatus()) ? cout << "user3 id: " << user3.getId() << endl :
                          cout << "Object Construction Failed" << endl;
    User user4;
    (User::getStatus()) ? cout << "user4 id: " << user4.getId() << endl :
                          cout << "Object Construction Failed" << endl;
    User user5;
    (User::getStatus()) ? cout << "user5 id: " << user5.getId() << endl :
                          cout << "Object Construction Failed" << endl;
    User user6;
    (User::getStatus()) ? cout << "user6 id: " << user6.getId() << endl :
                          cout << "Object Construction Failed" << endl;
    User user7;
    (User::getStatus()) ? cout << "user7 id: " << user7.getId() << endl :
                          cout << "Object Construction Failed" << endl;

    return 0;
}
于 2017-03-12T14:48:19.663 回答
0
static int a;//file scope variable
void getVol()
{
    static int b;//fixed duration
}

文件范围变量的行为与全局变量完全相同,只是它们的使用仅限于声明它们的文件(这意味着您不能将它们外部到其他文件)。 固定持续时间变量是即使在创建它的范围已退出后仍保留其值的变量!固定持续时间变量只创建(和初始化)一次,然后它们会在程序的整个生命周期中持续存在。检查此链接: http: //www.learncpp.com/cpp-tutorial/43-file-scope-and-the-static-keyword/

于 2013-08-09T05:40:05.960 回答
0

在块范围内使用 static 关键字就其存储位置而言与全局变量完全相同,但不同之处在于它只能在声明它的块范围内访问。回想一下,当您嵌套块时,最里面的块在引用标识符时优先——这同样适用于静态变量。

考虑以下代码片段来说明我的响应:

#include <stdio.h>

void f1( void ) {
    static int a = 10;
    {
        static int a = 9;

        printf( "inner a = %d\n", a );
    }

    printf( "outer a = %d\n", a );
}

int main( void ) {
    for ( int i = 0; i < 10; i++ ) {
        printf( "Calling the function f1.\n" );

        f1();
    }

    return 0;
}
于 2013-08-09T05:34:43.333 回答