【发布时间】:2010-10-30 21:45:36
【问题描述】:
C 和 C++ 中的 static 关键字有什么区别?
【问题讨论】:
-
我不是在询问类成员(数据或函数)静态部分。在 C 和 C++ 的文件范围内定义的静态变量的语义有什么不同吗??
C 和 C++ 中的 static 关键字有什么区别?
【问题讨论】:
static 关键字在 C 和 C++ 中的用途相同。
在文件级别(函数外部)使用时,它设置应用它的项目的可见性。静态项在其编译单元之外不可见(例如,对于链接器)。它们的持续时间与程序的持续时间相同。
这些文件级项目(函数和数据)应该是静态的,除非有特殊需要从外部访问它们(并且几乎不需要直接访问数据,因为这破坏了封装的核心原则)。
如果(正如您对问题的评论所示)这是您所关心的 static 的唯一用途,那么,不,C 和 C++ 之间没有区别。
在函数中使用时,它设置项目的持续时间。同样,持续时间与程序相同,并且该项目在该函数的调用之间继续存在。
它不会影响该项目的可见性,因为它仅在函数内可见。一个例子是一个随机数生成器,它需要在调用之间保持其种子值,但不希望该值对其他函数可见。
C++ 还有一个用途,static 在一个类中。当在那里使用时,它成为一个单一的类变量,在该类的所有对象中都是通用的。一个经典示例是存储已为给定类实例化的对象的数量。
正如其他人所指出的,文件级静态的使用已被弃用,取而代之的是未命名的命名空间。但是,我相信在它真正从语言中删除之前,在某个温暖的地方会是一个寒冷的日子——目前使用它的代码太多了。并且 ISO C 只是刚刚移除了 gets(),尽管我们都知道这是一个危险的函数。
即使它已被弃用,也不会改变其语义现在。
【讨论】:
在文件范围内使用 static 来限制对当前翻译单元的访问在 C++ 中已弃用,但在 C 中仍然可以接受。
改为使用未命名的命名空间
namespace
{
int file_scope_x;
}
以这种方式声明的变量仅在文件中可用,就像它们被声明为静态一样。
弃用的主要原因是删除 static 关键字的几个重载含义之一。
最初,这意味着变量(例如在函数中)将在程序的生命周期中存储在此类变量的区域中,而不是像通常用于函数局部变量的那样存储在堆栈中。
然后关键字被重载以应用于文件范围链接。根据需要组成新关键字是不可取的,因为它们可能会破坏现有代码。所以这个变量再次以不同的含义使用而不会引起冲突,因为声明为静态的变量不能同时在函数内部和顶层,并且函数之前没有修饰符。 (当提到函数时,存储的含义就完全消失了,因为它们没有存储在任何地方。)
当类出现在 C++(以及 Java 和 C#)中时,该关键字再次被使用,但其含义至少更接近最初的意图。以这种方式声明的变量存储在全局区域中,而不是像函数变量那样存储在堆栈中,或者像对象成员那样存储在堆中。因为变量不能同时位于顶层和类定义中,所以可以明确地将额外的含义附加到类变量上。它们只能通过类名或从该类的对象中引用。
【讨论】:
它在两种语言中的含义相同。
但是 C++ 增加了类。在类(以及结构)的上下文中,它具有使方法/变量类成员而不是对象成员的额外含义。
class Plop
{
static int x; // This is a member of the class not an instance.
public:
static int getX() // method is a member of the class.
{
return x;
}
};
int Plop::x = 5;
【讨论】:
请注意,使用 static 来表示“文件范围”(也称为命名空间范围)仅被 C++ 标准反对用于对象,而不是用于函数。换句话说,:
// foo.cpp
static int x = 0; // deprecated
static int f() { return 1; } // not deprecated
引用标准的附录 D:
static关键字的使用是 在声明对象时不推荐使用 命名空间范围。
【讨论】:
您不能在 C 中的结构内声明静态变量...但在 Cpp 中允许在范围解析运算符的帮助下。
在 Cpp 中静态函数也只能访问静态变量,但在 C 中静态函数可以有静态和非静态变量...?
【讨论】: