关键字static在c++中有多种含义,我觉得非常困惑,我永远无法思考它实际上应该如何工作。
根据我的理解,有一个静态存储持续时间,这意味着它在全局变量的情况下持续整个程序的生命周期,但当你谈论局部变量时,这意味着它默认是零初始化的。
c++标准对关键字为static的类数据成员这样说:
3.7.1静态存储时长[basic.stc.static]
关键字static可以用来声明一个具有静态存储持续时间的局部变量。
在类定义中应用于类数据成员的关键字static给出了数据成员的静态存储持续时间。
局部变量是什么意思?这是一个函数局部变量吗?因为当你将一个函数声明为静态时它只初始化了一次,也就是它第一次进入这个函数时。
它也只讨论了类成员的存储持续时间,它不是特定于实例的,这也是static的一个属性?或者是储存时间?
那么静态作用域和文件作用域的情况呢?默认情况下,是否所有全局变量都被认为具有静态存储持续时间?以下(来自第3.7.1节)似乎表明了这一点:
所有没有动态存储持续时间、没有线程存储持续时间和不是本地的变量都有静态存储持续时间。这些实体的存储应在程序期间持续(3.6.2,3.6.3)。
静态与变量的联系是怎样的?
这整个静态关键字是完全令人困惑的,有人能澄清它的不同用途的英语,并告诉我什么时候初始化一个静态类成员?
其实很简单。如果在函数的作用域中将变量声明为静态变量,则它的值将在对该函数的连续调用之间保留。所以:
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本质上是相同的变量。至于初始化,请参见这个问题。
其实很简单。如果在函数的作用域中将变量声明为静态变量,则它的值将在对该函数的连续调用之间保留。所以:
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本质上是相同的变量。至于初始化,请参见这个问题。
静态存储持续时间意味着变量在程序的整个生命周期内都驻留在内存中的相同位置。
连杆与这个正交。
我认为这是你能做的最重要的区分。理解这一点和其他的,以及记住它,应该很容易(不是直接针对@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,达到了这样的效果-混淆。它用来表示不同的事情(我可以说,可能是相反的事情)。
局部变量是什么意思?这是一个函数局部变量吗?
是-非全局,如函数局部变量。
因为当你将一个函数声明为静态时它只初始化了一次,也就是它第一次进入这个函数时。
正确的。
它也只讨论了类成员的存储持续时间,它不是特定于实例的,这也是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.
静态变量在类的每个实例之间共享,而不是每个类都有自己的变量。
class MyClass
{
public:
int myVar;
static int myStaticVar;
};
//Static member variables must be initialized. Unless you're using C++11, or it's an integer type,
//they have to be defined and initialized outside of the class like this:
MyClass::myStaticVar = 0;
MyClass classA;
MyClass classB;
'MyClass'的每个实例都有自己的'myVar',但共享相同的'myStaticVar'。
事实上,你甚至不需要MyClass的一个实例来访问'myStaticVar',你可以像这样在类外部访问它:
MyClass::myStaticVar //Assuming it's publicly accessible.
当在函数中作为局部变量(而不是类成员变量)使用时,static关键字的作用有所不同。它允许您创建一个持久变量,而不给予全局作用域。
int myFunc()
{
int myVar = 0; //Each time the code reaches here, a new variable called 'myVar' is initialized.
myVar++;
//Given the above code, this will *always* print '1'.
std::cout << myVar << std::endl;
//The first time the code reaches here, 'myStaticVar' is initialized. But ONLY the first time.
static int myStaticVar = 0;
//Each time the code reaches here, myStaticVar is incremented.
myStaticVar++;
//This will print a continuously incrementing number,
//each time the function is called. '1', '2', '3', etc...
std::cout << myStaticVar << std::endl;
}
就持久性而言,这是一个全局变量……但在范围/可访问性上没有全球性。
你也可以有静态成员函数。静态函数基本上是非成员函数,但是在类名的命名空间内,并且具有对类成员的私有访问。
class MyClass
{
public:
int Func()
{
//...do something...
}
static int StaticFunc()
{
//...do something...
}
};
int main()
{
MyClass myClassA;
myClassA.Func(); //Calls 'Func'.
myClassA.StaticFunc(); //Calls 'StaticFunc'.
MyClass::StaticFunc(); //Calls 'StaticFunc'.
MyClass::Func(); //Error: You can't call a non-static member-function without a class instance!
return 0;
}
当你调用一个成员函数时,有一个隐藏的形参叫做this,它是一个指向调用该函数的类实例的指针。
静态成员函数没有那个隐藏形参…它们可以在没有类实例的情况下被调用,但也不能访问类的非静态成员变量,因为它们没有“this”指针。它们不会被任何特定的类实例调用。
我不是一个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完全向后兼容。