【问题标题】:static and external variables静态和外部变量
【发布时间】:2011-03-10 19:36:23
【问题描述】:

静态变量和外部变量有什么区别?制作静态变量有什么好处? 为什么我们更喜欢在多功能程序中制作外部变量?这本书说,否则它会很晚才初始化。没看懂。

【问题讨论】:

  • C# 和 C++ 是非常不同的语言。由于 C# 中不存在“外部”变量的概念,我假设这是关于 C++ 的。
  • 您还指的是哪本书?知道名称/ISBN 以解决您的问题会很方便(页面也很方便)。
  • 让我们 c by yashwant kanetkar 和 turbo c by robert lafore
  • 重新标记,因为您提到的两本书都是 C,而不是 C++ 或 C#。重要区别。
  • herehere - 不幸的是,你在一个问题中将这两个关键字放在一起,否则我会投票关闭作为重复项。

标签: c


【解决方案1】:

“静态”或多或少意味着“这将永远存在”。根据上下文,您会得到不同的结果:

 static int global_variable;
 void function()
 {
      static int global_function_variable;
 }

 class foo
 {
      static void function()
      {
           static int foo_function_variable;
           //...
      }
      static int foo_variable;
 }

global_variable - 仅在“翻译单元”中可见。 (由于头文件或多或少被复制进来,这是否意味着头文件中的静态全局变量作为包含在其中的所有 cpp 文件的单独变量存在?)

global_function_variable 在第一次调用function 时创建,并将在程序的整个生命周期中继续存在。值 persists,所以如果你在一个函数调用中改变它,下一个函数调用将使用改变的变量。

foo::function()是一个可以像全局函数一样调用的函数;你不需要有foo 的实例来调用它。但是,这意味着它没有有效的this 指针。同样,即使没有任何 foo 对象,foo_variable 也存在。所有foo 对象都具有相同的foo_variable - 如果您在一个对象中更改它,所有其他对象都会“看到”更改。

foo_function_variable 的行为,我认为,就像 global_function_variable

extern 背后的基本思想是控制一个变量的链接: 来自MSDN

// specifying_linkage1.cpp
int i = 1;
void other();

int main() {
   // Reference to i, defined above:
   extern int i;
}

void other() {
   // Address of global i assigned to pointer variable:
   static int *external_i = &i;

   // i will be redefined; global i no longer visible:
   // int i = 16;
}

extern int global_variable;

extern 也可用于链接使用另一种语言的变量,最常见的是 C。

global_variable是extern最常见的用法;它说在其他地方,有一个名为“global_variable”的变量,我们将使用该变量。在某处,您需要声明变量没有 extern 关键字,否则它永远不会实际创建。

【讨论】:

    【解决方案2】:

    问题是在 C 中静态可以有不同的含义。我将尝试在以下段落中概述不同的情况。

    如果一个变量是在函数之外定义的,它可以被文件中的所有函数使用。有时也称为“全局变量”。这意味着整个文件只有一个此变量的实例。变量的名称也存储在生成的 .OBJ 文件中。后者很重要,因为如果另一个文件也在函数之外定义了一个同名的变量,则链接器会假定在这两种情况下它是同一个变量,并将它们合并。 为了更清楚地说明这一点,最好将关键字“extern”添加到其中一个变量中。在这种情况下,我们说我们声明了变量,而不是定义它。这是编译器/链接器的一个额外信号,表明我们实际上想要引用在其他地方定义的全局变量。

    如果你想定义一个全局变量,但又不想让它对其他文件可用,可以在前面加上关键字static。关键字 static 告诉编译器变量名不能存储在 .OBJ 文件中。这意味着两个 .C 文件具有以下行:

    static long MyGlobalVariable;
    

    每个人都有自己的变量。这两个变量都将被称为 MyGlobalVariable。

    如果你在函数内部定义了一个变量,它就变成了一个局部变量。如果函数被调用,它就会存在,并在函数完成后再次消失。 在某些情况下,您希望在函数调用之间保留变量的值。您可以通过使用全局变量(而不是局部变量)来执行此操作,但随后该变量可用于文件中的所有函数,而您不一定想要。在这种情况下,您可以将关键字 static 放在变量之前,如下所示:

    void MyFunction()
    {
    static long MyLocalVariable = 0;
    ++MyLocalVariable;
    }
    

    第一次调用函数时,MyLocalVariable 将被“创建”并初始化为值 0。在函数结束时,变量不会被销毁,而是被保留。所以下次调用这个函数时,变量的值会是 1,而不是 0。

    在 C 中,将变量放在函数外部(作为全局变量)还是在函数内部将其定义为静态并不重要。唯一的区别是可以访问变量的位置。

    在 C++ 中,情况完全不同。如果你写这个(在函数之外):

    MyClass MyGlobalVariable;
    

    MyGlobalVariable 将在应用程序开始时被构造(即:构造函数将被执行),甚至在调用 main 之前。但是,您无法真正控制所有全局变量的构造顺序。 所以如果另一个文件包含这个:

    MyOtherClass MySecondGlobalVariable;
    

    您无法确定是先构造 MyGlobalVariable 还是 MySecondGlobalVariable。如果其中一个的构造函数依赖于另一个的存在(构造),这可能会产生问题。

    另一方面,如果你在函数中将变量定义为静态:

    void MyFunction()
    {
    static MyClass MyStaticVariable;
    }
    

    那么 MyStaticVariable 将在第一次调用该函数时被构造。使用这种结构,您可以编写如下内容:

    MyClass &getMyClass()
    {
    static MyClass MySelf;
    return MySelf;
    }
    

    我们已经实现了一个单例,我们可以控制它的构建时间。我们第一次需要它时,它就被构建了。

    说实话,这种方法是一种相当简单的方法,因为它可能会导致多线程应用程序出现问题。在这种情况下,还有其他技巧。

    【讨论】:

    • 问题现在只标记为 C。
    • 关于你给出的例子,如果我重新启动程序,第一行是 static long MyLocalVariable = 0;这使它的值为0。那么它的值何时为1?
    • 在 ++MyLocalVariable 行之后,它的值是 1。如果我们稍后重新进入函数,值仍然是 1,而在 ++MyLocalVariable 行之后,它的值将是2.等等。重要的是要看到初始化为零仅在第一次输入函数时执行(或更准确地说,在变量“构造”的那一刻)。
    猜你喜欢
    • 2021-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-18
    • 1970-01-01
    • 2011-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多