【问题标题】:What is the difference between a static and const variable?静态变量和常量变量有什么区别?
【发布时间】:2011-01-14 01:07:07
【问题描述】:

有人能解释一下staticconst 变量之间的区别吗?

【问题讨论】:

  • @jagannath :是的,他可以,但是如果他是一个非常熟练的 Fortran 程序员,被 Fortran 编程书籍包围,有一个 C 源代码可以在压力下调试并且不知道去哪里找呢? stackoverflow 也为那些知道的人提供简单的问题,但对于那些不知道的人来说很困难。
  • static 和 const 仅在 C++ 中听起来相同。但是这里的静态意味着它仍然活着,不会被垃圾,在这个意义上与动态相反。而 const,就是那个常数。

标签: c++ c static constants


【解决方案1】:

一个常数值不能改变。静态变量存在于函数或类中,而不是实例或对象。

这两个概念并不相互排斥,可以一起使用。

【讨论】:

  • 还有静态全局变量,它们是在函数和类之外声明的静态变量。我相信唯一的目的是文件范围。
  • @Swiss: 是的,static int fileScopeFoo = 42;namespace { int fileScopeFoo = 42; } 的弃用替代品
  • 据我所知,静态全局变量在 C 中不被弃用,因为没有命名空间。
  • 听起来像是一个面向对象的答案。
  • 对静态变量的很好解释,也很简洁。如果将文本“exists to a”更改为“exists for a”,可能会更好读。
【解决方案2】:

简短的回答:

const 承诺一旦设置,您将不会尝试修改该值。

static 变量意味着对象的生命周期是程序的整个执行过程,并且它的值仅在程序启动前初始化一次。如果您没有为它们显式设置值,则所有静态都将被初始化。静态初始化的方式和时间是未指定

C99 从 C++ 借用了 const 的用法。另一方面,static 一直是许多争论的根源(两种语言),因为它经常混淆语义。

此外,在 C++11 之前的 C++0x 中,不推荐使用 static 关键字来声明命名空间范围内的对象。由于各种原因,此弃用已在 C++11 中删除(请参阅here)。

更长的答案:比您想知道的更多关键字(直接来自标准):

C99

#include <fenv.h>
#pragma STDC FENV_ACCESS ON

/* file scope, static storage, internal linkage */
static int i1; // tentative definition, internal linkage
extern int i1; // tentative definition, internal linkage

int i2; // external linkage, automatic duration (effectively lifetime of program)

int *p = (int []){2, 4}; // unnamed array has static storage

/* effect on string literals */
char *s = "/tmp/fileXXXXXX"; // static storage always, may not be modifiable
char *p = (char []){"/tmp/fileXXXXXX"}; // static, modifiable
const char *cp = (const char []){"/tmp/fileXXXXXX"}  // static, non-modifiable


void f(int m)
{
    static int vla[ m ]; // err

    float w[] = { 0.0/0.0 }; // raises an exception

    /* block scope, static storage, no-linkage */
    static float x = 0.0/0.0; // does not raise an exception
    /* ... */
     /* effect on string literals */
    char *s = "/tmp/fileXXXXXX"; // static storage always, may not be modifiable
    char *p = (char []){"/tmp/fileXXXXXX"}; // automatic storage, modifiable
    const char *cp = (const char []){"/tmp/fileXXXXXX"}  // automatic storage, non-modifiable

}

inline void bar(void)
{
     const static int x = 42; // ok
     // Note: Since an inline definition is distinct from the 
     // corresponding external definition and from any other
     // corresponding inline definitions in other translation 
     // units, all corresponding objects with static storage
     // duration are also distinct in each of the definitions
     static int y = -42; // error, inline function definition
}

// the last declaration also specifies that the argument 
// corresponding to a in any call to f must be a non-null 
// pointer to the first of at least three arrays of 5 doubles
void f(double a[static 3][5]);

static void g(void); // internal linkage

C++

除了简短回答中提到的以外,大部分情况下具有相同的语义。此外,没有参数限定statics。

extern "C" {
static void f4(); // the name of the function f4 has
                  // internal linkage (not C language
                  // linkage) and the function’s type
                  // has C language linkage.
}

class S {
   mutable static int i; // err
   mutable static int j; // err
   static int k; // ok, all instances share the same member
};

inline void bar(void)
{
     const static int x = 42; // ok
     static int y = -42; // ok
}

我在这里省略了 C++ 的static 的更多细微差别。看看一本书或标准。

【讨论】:

  • 我不明白为什么static int y = -42; 会出错。可以说这样做不太聪明,但我认为这是非常合法的。 (见stackoverflow.com/questions/2217628/…
  • @litb:因为在 C99 中,函数的内联定义不允许有可修改的静态对象定义。见 6.7.4。第 3 段和下一页的相关脚注(可能)。
  • 您知道限制的原因吗?我的意思是,已经允许内联定义公开不同的行为。为什么它们仅限于不可修改的对象定义并禁止使用具有内部链接的标识符?我想这样的静态变量可能对调试/等有用。有什么想法吗?
  • @litb:如果它是非常量,则根据脚注“120”)由于内联定义不同于相应的外部定义以及其他翻译单元中的任何其他相应的内联定义,因此所有相应的对象在每个定义中,静态存储持续时间也是不同的。”草案和 6.7.4 第 6 段,IMO,在任何给定时间,对象的值将是无法确定的(该值可以来自外部定义/内部定义,具体取决于编译器如何以及在何处做出选择。
【解决方案3】:

静态变量:

  • 仅初始化一次。
  • 静态变量用于类(不是每个对象)。即每个类只分配一次内存,每个实例都使用它。因此,如果一个对象修改了它的值,那么修改后的值对其他对象也是可见的。 (一个简单的想法。要知道为一个类创建的对象的数量,我们可以放置一个静态变量并在构造函数中执行 ++)
  • 值在不同的函数调用之间保持不变

常量变量:

  • Const 变量承诺您不会在程序中的任何地方更改其值。如果你这样做,它会抱怨。

【讨论】:

    【解决方案4】:

    const 等价于#define,但仅用于值语句(例如#define myvalue = 2)。声明的值替换编译前的变量名。

    static 是一个变量。值可以改变,但变量将在整个程序执行过程中保持即使该变量是在函数中声明的。相当于一个全局变量,其使用范围是声明它们的块的范围,但其值的范围是全局的。

    因此,静态变量只初始化一次。如果变量在函数中声明,这一点尤其重要,因为它保证初始化只会在第一次调用函数时发生

    静态的另一种用法涉及对象。在对象中声明静态变量的效果是该值对于对象的所有实例都是相同的。因此,它不能用对象的名字来调用,而只能用类的名字来调用。

    public class Test 
    { 
        public static int test;
    }
    Test myTestObject=new Test();
    myTestObject.test=2;//ERROR
    Test.test=2;//Correct
    

    在 C 和 C++ 等语言中,声明静态全局变量是没有意义的,但它们在函数和类中非常有用。 在托管语言中,具有全局变量效果的唯一方法是将其声明为静态。

    【讨论】:

      【解决方案5】:

      常量无法更改,静态变量更多地与它们的分配方式和可访问位置有关。

      看看这个site

      【讨论】:

      • 链接已断开
      【解决方案6】:
      static is a storage specifier.
      const is a type qualifier.
      

      【讨论】:

        【解决方案7】:

        静态变量在一个类型的所有实例中是通用的。

        常量变量特定于某个类型的每个单独实例,但它们的值在编译时是已知的和固定的,并且不能在运行时更改。

        与常量不同,静态变量值可以在运行时更改。

        【讨论】:

          【解决方案8】:

          静态变量只能获得一次初始值。这意味着如果您在示例函数中有诸如“static int a=0”之类的代码,并且该代码在该函数的第一次调用中执行,但在该函数的后续调用中未执行;变量 (a) 仍将具有其当前值(例如,当前值为 5),因为静态变量仅获得一次初始值。

          常量变量的值在整个代码中都是常量。例如,如果您设置了“const int a=5”这样的常量变量,那么“a”的值将在整个程序中保持不变。

          【讨论】:

            【解决方案9】:

            类上下文中的静态变量在类的所有实例之间共享。

            在函数中,它仍然是一个持久变量,因此您可以例如计算函数被调用的次数。

            在函数或类之外使用时,它确保该变量只能由该特定文件中的代码使用,而不能用于其他任何地方。

            然而,常量变量被阻止改变。 const 和 static 一起使用的常见用法是在类定义中提供某种常量。

            class myClass {
            public:
                 static const int TOTAL_NUMBER = 5;
                 // some public stuff
            private:
                 // some stuff
            };
            

            【讨论】:

              【解决方案10】:

              static 意味着编译单元的本地(即单个 C++ 源代码文件),或者换句话说,它意味着它没有添加到全局命名空间中。您可以在不同的 c++ 源代码文件中拥有多个具有相同名称且没有名称冲突的静态变量。

              const 只是常量,意思是不能修改。

              【讨论】:

              • 在 C++ 中,匿名命名空间优于静态文件范围变量。
              • @JonathanLeffler 为什么会这样?为未知命名空间块获得另一个级别的缩进并增加圈复杂度?还是避免在所有静态函数前面写静态?我认为使用静态而不是匿名命名空间与使用未命名命名空间一样可取,这是编程风格偏好的问题。
              • @BitTickler:请参阅Deprecation of the static keyword -- no more? 进行讨论。我在 2010 年不知道 Q&A 说了什么——它是在 2011 年写的。
              【解决方案11】:

              Const 表示“无法更改”。

              静态的意思是“静态实例(在内存中) vs 动态实例(在堆栈上)。”静态变量在程序运行期间一直存在。动态的会根据需要创建和销毁。

              变量可以是一个或两个。

              【讨论】:

                【解决方案12】:

                const 表示常量,它们的值是在编译时定义的,而不是在运行时显式更改,常量的值在运行时不能更改

                然而,静态变量是可以在运行时初始化和更改的变量。然而,静态变量在这个意义上与变量不同,静态变量在整个程序中保留它们的值,即它们的生命周期是程序的,或者直到程序使用动态分配方法释放内存为止。然而,即使它们在程序的整个生命周期内都保留了它们的值,但它们在它们所在的代码块之外是不可访问的

                有关静态变量的更多信息,请参阅here

                【讨论】:

                  【解决方案13】:

                  常量变量不能更改。静态变量是文件私有的,只能在程序代码中访问,其他任何人都不能访问。

                  【讨论】:

                    【解决方案14】:

                    static关键字定义了变量的作用域,而const关键字定义了程序执行过程中不能改变的变量值

                    【讨论】:

                      【解决方案15】:

                      简单而简短的回答是内存只分配给静态和常量一次。但是在 const 中,这仅适用于一个值,而静态值可能会发生变化,但内存区域保持不变,直到程序结束。

                      【讨论】:

                      • 这不是真的。对于const,编译器可以将原始值放入目标代码中,就好像它是#define(带有花里胡哨的)
                      【解决方案16】:

                      静态

                      用于使变量成为类变量。声明时不需要定义静态变量。

                      例子:

                      #include <iostream>
                      
                      class dummy
                      {
                              public:
                                      static int dum;
                      };
                      
                      
                      int dummy::dum = 0; //This is important for static variable, otherwise you'd get a linking error
                      
                      int main()
                      {
                              dummy d;
                              d.dum = 1;
                      
                              std::cout<<"Printing dum from object: "<<d.dum<<std::endl;
                              std::cout<<"Printing dum from class: "<<dummy::dum<<std::endl;
                      
                              return 0;
                      }
                      

                      这将打印: 从对象打印dum:1 类打印内存:1

                      变量dum是一个类变量。尝试通过对象访问它只会通知编译器它是哪个类的变量。 考虑一个场景,您可以使用一个变量来计算创建的对象的数量。静态在那里会派上用场。

                      常量

                      用于使其成为只读变量。您需要立即定义和声明 const 变量。

                      在上面提到的同一个程序中,让我们也将 dum 设为 const:

                      class dummy
                      {
                              public:
                                      static const int dum; // This would give an error. You need to define it as well
                                      static const int dum = 1; //this is correct
                                      const int dum = 1; //Correct. Just not making it a class variable
                      
                      };
                      

                      假设我主要是这样做的:

                      int main()
                      {
                              dummy d;
                              d.dum = 1; //Illegal!
                      
                              std::cout<<"Printing dum from object: "<<d.dum<<std::endl;
                              std::cout<<"Printing dum from class: "<<dummy::dum<<std::endl;
                      
                              return 0;
                      }
                      

                      虽然 static 易于理解,但 const 在 c++ 中却是一团糟。以下资源有助于更好地理解它: http://duramecho.com/ComputerInformation/WhyHowCppConst.html

                      【讨论】:

                        【解决方案17】:

                        静态值可以存在于函数中,可以以不同的形式使用,在程序中可以有不同的值。 同样在程序过程中,在递增递减之后,它们的值可能会改变,但在整个程序期间保持不变。

                        【讨论】:

                          猜你喜欢
                          • 2010-09-25
                          • 2012-10-22
                          • 2021-04-20
                          • 1970-01-01
                          • 2014-06-25
                          • 2015-08-11
                          • 2019-03-16
                          • 2020-07-13
                          相关资源
                          最近更新 更多