关键字static在c++中有多种含义,我觉得非常困惑,我永远无法思考它实际上应该如何工作。

根据我的理解,有一个静态存储持续时间,这意味着它在全局变量的情况下持续整个程序的生命周期,但当你谈论局部变量时,这意味着它默认是零初始化的。

c++标准对关键字为static的类数据成员这样说:

3.7.1静态存储时长[basic.stc.static]

关键字static可以用来声明一个具有静态存储持续时间的局部变量。 在类定义中应用于类数据成员的关键字static给出了数据成员的静态存储持续时间。

局部变量是什么意思?这是一个函数局部变量吗?因为当你将一个函数声明为静态时它只初始化了一次,也就是它第一次进入这个函数时。

它也只讨论了类成员的存储持续时间,它不是特定于实例的,这也是static的一个属性?或者是储存时间?

那么静态作用域和文件作用域的情况呢?默认情况下,是否所有全局变量都被认为具有静态存储持续时间?以下(来自第3.7.1节)似乎表明了这一点:

所有没有动态存储持续时间、没有线程存储持续时间和不是本地的变量都有静态存储持续时间。这些实体的存储应在程序期间持续(3.6.2,3.6.3)。

静态与变量的联系是怎样的?

这整个静态关键字是完全令人困惑的,有人能澄清它的不同用途的英语,并告诉我什么时候初始化一个静态类成员?


当前回答

局部变量是什么意思?这是一个函数局部变量吗?

是-非全局,如函数局部变量。

因为当你将一个函数声明为静态时它只初始化了一次,也就是它第一次进入这个函数时。

正确的。

它也只讨论了类成员的存储持续时间,它不是特定于实例的,这也是static的一个属性?或者是储存时间?

class R { static int a; }; // << static lives for the duration of the program

也就是说,R的所有实例共享int R::a——int R::a永远不会被复制。

那么静态作用域和文件作用域的情况呢?

有效地,在适当的地方具有构造函数/析构函数的全局变量——初始化不会延迟到访问。

静态与变量的联系是怎样的?

对于局部函数,它是外部函数。访问:函数可以访问它(当然,除非您返回它)。

对于类来说,它是外部的。访问:应用标准访问说明符(公共、受保护、私有)。

Static还可以指定内部链接,这取决于它声明的位置(文件/名称空间)。

整个静态关键字完全令人困惑

它在c++中有太多的用途。

有人能澄清它英语的不同用途,并告诉我什么时候初始化一个静态类成员?

It's automatically initialized before main if it's loaded and has a constructor. That might sound like a good thing, but initialization order is largely beyond your control, so complex initialization becomes very difficult to maintain, and you want to minimize this -- if you must have a static, then function local scales much better across libraries and projects. As far as data with static storage duration, you should try to minimize this design, particularly if mutable (global variables). Initialization 'time' also varies for a number of reasons -- the loader and kernel have some tricks to minimize memory footprints and defer initialization, depending on the data in question.

其他回答

当您在文件范围内声明一个静态变量时,那么该变量仅在该特定文件中可用(技术上是*翻译单元,但我们不要把它复杂化)。例如:

a.cpp

static int x = 7;

void printax()
{
    cout << "from a.cpp: x=" << x << endl;
}

b.cpp

static int x = 9;

void printbx()
{
    cout << "from b.cpp: x=" << x << endl;
}

main.cpp:

int main(int, char **)
{
    printax(); // Will print 7
    printbx(); // Will print 9

    return 0;
}

对于局部变量,static意味着变量将被零初始化,并在调用之间保留其值:

unsigned int powersoftwo()
{
    static unsigned lastpow;

    if(lastpow == 0)
        lastpow = 1;
    else
        lastpow *= 2;

    return lastpow;
}

int main(int, char **)
{
    for(int i = 0; i != 10; i++)
        cout << "2^" << i << " = " << powersoftwo() << endl;
}

对于类变量,这意味着该类的所有成员之间只共享该变量的一个实例。根据权限的不同,可以从类外部使用完全限定名访问变量。

class Test
{
private:
    static char *xxx;

public:
    static int yyy;

public:
    Test()
    {        
        cout << this << "The static class variable xxx is at address "
             << static_cast<void *>(xxx) << endl;
        cout << this << "The static class variable yyy is at address "
             << static_cast<void *>(&y) << endl;
    }
};

// Necessary for static class variables.
char *Test::xxx = "I'm Triple X!";
int Test::yyy = 0;

int main(int, char **)
{
    Test t1;
    Test t2;

    Test::yyy = 666;

    Test t3;
};

将非类函数标记为静态使该函数只能从该文件访问,而不能从其他文件访问。

a.cpp

static void printfilename()
{ // this is the printfilename from a.cpp - 
  // it can't be accessed from any other file
    cout << "this is a.cpp" << endl;
}

b.cpp

static void printfilename()
{ // this is the printfilename from b.cpp - 
  // it can't be accessed from any other file
    cout << "this is b.cpp" << endl;
}

对于类成员函数,将它们标记为静态意味着该函数不需要在对象的特定实例上调用(即它没有this指针)。

class Test
{
private:
    static int count;

public:
    static int GetTestCount()
    {
        return count;
    };

    Test()
    {
        cout << this << "Created an instance of Test" << endl;
        count++;
    }

    ~Test()
    {
        cout << this << "Destroyed an instance of Test" << endl;
        count--;
    }
};

int Test::count = 0;

int main(int, char **)
{
    Test *arr[10] = { NULL };

    for(int i = 0; i != 10; i++)
        arr[i] = new Test();

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    // now, delete them all except the first and last!
    for(int i = 1; i != 9; i++)
        delete arr[i];        

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    delete arr[0];

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    delete arr[9];

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    return 0;
}

其实很简单。如果在函数的作用域中将变量声明为静态变量,则它的值将在对该函数的连续调用之间保留。所以:

int myFun()
{
static int i=5;
i++;
return i;
}
int main()
{
printf("%d", myFun());
printf("%d", myFun());
printf("%d", myFun());
}

将显示678而不是666,因为它记住了增加的值。

至于静态成员,它们在类的实例之间保存它们的值。下面的代码:

struct A
{
static int a;
};
int main()
{
A first;
A second;
first.a = 3;
second.a = 4;
printf("%d", first.a);
}

将打印4,因为首先。一个和第二个。A本质上是相同的变量。至于初始化,请参见这个问题。

静态对象:我们可以使用关键字Static定义类成员Static。当我们将类的成员声明为静态时,这意味着无论创建了多少个类的对象,都只有一个静态成员的副本。

静态成员由类的所有对象共享。在创建第一个对象时,如果没有其他初始化,则所有静态数据都初始化为零。我们不能把它放在类定义中,但它可以在类外初始化,就像下面的例子中那样,通过重新声明静态变量,使用范围解析操作符::来确定它属于哪个类。

让我们尝试下面的例子来理解静态数据成员的概念:

#include <iostream>

using namespace std;

class Box
{
   public:
      static int objectCount;
      // Constructor definition
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
         // Increase every time object is created
         objectCount++;
      }
      double Volume()
      {
         return length * breadth * height;
      }
   private:
      double length;     // Length of a box
      double breadth;    // Breadth of a box
      double height;     // Height of a box
};

// Initialize static member of class Box
int Box::objectCount = 0;

int main(void)
{
   Box Box1(3.3, 1.2, 1.5);    // Declare box1
   Box Box2(8.5, 6.0, 2.0);    // Declare box2

   // Print total number of objects.
   cout << "Total objects: " << Box::objectCount << endl;

   return 0;
}

当上面的代码被编译和执行时,它会产生以下结果:

Constructor called.
Constructor called.
Total objects: 2

静态函数成员: 通过将函数成员声明为静态,可以使它独立于类的任何特定对象。即使类不存在对象,并且只使用类名和作用域解析操作符::访问静态函数,也可以调用静态成员函数。

静态成员函数只能从类外部访问静态数据成员、其他静态成员函数和任何其他函数。

静态成员函数有一个类作用域,它们不能访问类的this指针。您可以使用静态成员函数来确定类的某些对象是否已经创建。

让我们尝试下面的例子来理解静态函数成员的概念:

#include <iostream>

using namespace std;

class Box
{
   public:
      static int objectCount;
      // Constructor definition
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
         // Increase every time object is created
         objectCount++;
      }
      double Volume()
      {
         return length * breadth * height;
      }
      static int getCount()
      {
         return objectCount;
      }
   private:
      double length;     // Length of a box
      double breadth;    // Breadth of a box
      double height;     // Height of a box
};

// Initialize static member of class Box
int Box::objectCount = 0;

int main(void)
{

   // Print total number of objects before creating object.
   cout << "Inital Stage Count: " << Box::getCount() << endl;

   Box Box1(3.3, 1.2, 1.5);    // Declare box1
   Box Box2(8.5, 6.0, 2.0);    // Declare box2

   // Print total number of objects after creating object.
   cout << "Final Stage Count: " << Box::getCount() << endl;

   return 0;
}

当上面的代码被编译和执行时,它会产生以下结果:

Inital Stage Count: 0
Constructor called.
Constructor called.
Final Stage Count: 2

静态存储持续时间意味着变量在程序的整个生命周期内都驻留在内存中的相同位置。

连杆与这个正交。

我认为这是你能做的最重要的区分。理解这一点和其他的,以及记住它,应该很容易(不是直接针对@Tony,而是将来可能会看到这篇文章的人)。

关键字static可以用来表示内部链接和静态存储,但本质上它们是不同的。

局部变量是什么意思?这是一个函数局部变量吗?

是的。不管变量是什么时候初始化的(在第一次调用函数时以及执行路径到达声明点时),它在程序生命周期内都将驻留在内存中的相同位置。在这种情况下,静态为它提供静态存储。

那么静态作用域和文件作用域的情况呢?默认情况下,是否所有全局变量都被认为具有静态存储持续时间?

是的,根据定义,所有全局变量都有静态存储持续时间(现在我们已经澄清了这意味着什么)。但是命名空间作用域变量没有使用static声明,因为那样会给它们内部链接,所以每个翻译单元都有一个变量。

静态与变量的联系是怎样的?

它提供了名称空间作用域变量的内部链接。它为成员和局部变量提供静态存储持续时间。

让我们扩展一下:

//

static int x; //internal linkage
              //non-static storage - each translation unit will have its own copy of x
              //NOT A TRUE GLOBAL!

int y;        //static storage duration (can be used with extern)
              //actual global
              //external linkage
struct X
{
   static int x;     //static storage duration - shared between class instances 
};

void foo()
{
   static int x;     //static storage duration - shared between calls
}

整个静态关键字完全令人困惑

当然,除非你对它很熟悉。:)为了避免在语言中添加新的关键词,委员会重新使用了这个词,IMO,达到了这样的效果-混淆。它用来表示不同的事情(我可以说,可能是相反的事情)。

我不是一个C程序员,所以我不能给你关于静态在C程序中正确使用的信息,但当涉及到面向对象编程时,静态基本上声明一个变量,或一个函数或一个类在程序的整个生命周期中是相同的。举个例子。

class A
{
public:
    A();
    ~A();
    void somePublicMethod();
private:
    void somePrivateMethod();
};

当你在Main中实例化这个类时,你可以这样做。

int main()
{
   A a1;
   //do something on a1
   A a2;
   //do something on a2
}

这两个类实例彼此完全不同,彼此独立操作。但如果你像这样重新创建A类。

class A
{
public:
    A();
    ~A();
    void somePublicMethod();
    static int x;
private:
    void somePrivateMethod();
};

让我们再回到主体部分。

int main()
{
   A a1;
   a1.x = 1;
   //do something on a1
   A a2;
   a2.x++;
   //do something on a2
}

那么a1和a2将共享同一个int x副本,因此a1中对x的任何操作都将直接影响a2中x的操作。如果我要这么做

int main()
{
   A a1;
   a1.x = 1;
   //do something on a1
   cout << a1.x << endl; //this would be 1
   A a2;
   a2.x++;
   cout << a2.x << endl; //this would be 2 
   //do something on a2
}

类A的两个实例共享静态变量和函数。希望这能回答你的问题。我有限的C语言知识允许我说,将函数或变量定义为静态意味着它只对函数或变量定义为静态的文件可见。但这个问题最好由一个C男来回答,而不是我。c++允许用C和c++两种方式将变量声明为静态,因为它与C完全向后兼容。