在不同范围内声明的静态变量之间的差异

时间:2013-08-09 05:31:02

标签: c++ static

在块中声明静态变量和在文件中的块外部之间有什么区别?例如,这里,静态变量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;
    }

6 个答案:

答案 0 :(得分:10)

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

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

  1. 静态生命周期 - 它存在于程序的整个生命周期中。
  2. 本地可见性 - 该名称在声明范围之外不可见。
  3. 无论是在块内部还是外部定义的静态变量,这两者都是正确的。默认情况下会发生一部分或另一部分,即使您不使用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 not 常量初始化,而goto意味着执行永远不会流经其初始化 - 因此,它将保留它之前初始化的0发生了任何其他初始化,因此(使用正常运行的编译器)输出将是:

    1 
    0
    

答案 1 :(得分:1)

static int a;

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

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

表示局部变量b具有从程序开始到程序结束的生命周期,即,您可以为其分配一些值,而在下次调用该函数时,它会记住该值。

cdb类似。

答案 2 :(得分:1)

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

  1. 在块/功能
  2. 之外不可见
  3. 它的值保留在函数调用中,因为它是静态的
  4. 块外的静态变量(全局静态变量) -

    1. 它的范围是整个文件(如程序中的 a
    2. 它的值保留在函数调用之间,因为它是静态的。

答案 3 :(得分: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;
}

答案 4 :(得分: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;
}

答案 5 :(得分: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/