代码之家  ›  专栏  ›  技术社区  ›  Naveen

C和C++中的静态变量

  •  16
  • Naveen  · 技术社区  · 15 年前

    变量声明为 static 在C和C++之间的任何函数外。我读到了 静止的 意味着文件范围和变量在文件之外是不可访问的。在C语言中,全局变量是 静止的 . 这是否意味着C中的全局变量不能在另一个文件中访问?

    5 回复  |  直到 15 年前
        1
  •  16
  •   Community CDub    7 年前

    不,C和C++在这方面没有区别。

    this SO answer 关于什么 static 表示在C程序中。在C++中还有一些与使用 静止的 对于类变量(而不是实例变量)。

    关于全局变量 静止的 -只有从内存分配的角度来看(它们是在数据段上分配的,就像所有全局的一样)。从可视性的角度来看:

    static int var;    // can't be seen from outside files
    int var;           // can be seen from outside files (no 'static')
    
        2
  •  7
  •   Clifford    15 年前

    这里有两个概念“静态 联动装置 (或范围)“和静态 分配 “。

    在函数外部,关键字指的是链接,在函数内部指的是分配。函数外部的所有变量都隐式具有静态分配。也许是个不幸的设计,但它确实存在。

        3
  •  5
  •   Southern Hospitality    15 年前

    C和C++是一样的。

    Static做了两件不同的事情。

    对于在函数范围之外声明的变量,它会更改变量的可见性(链接)。该变量将是一个全局变量,因为它不在函数范围内。如果它不是静态的,它将具有通用链接(可见性),因此任何与此链接在一起的代码都可以访问它(它们可能必须声明它是外部的)。如果变量在函数作用域之外并且是静态的,那么它仍然是一个全局变量,因为它始终存在并保持其值,但是同一编译单元(该.c文件和包含的任何.h文件)之外的任何代码都不能访问它。

    对于在函数范围内声明的变量,static将更改存储变量的位置。如果它不是静态的,它将是一个自动变量,这意味着当函数退出时,它将消失,当再次输入函数时,它将恢复存在(在堆栈上)。当您退出函数时,它将丢失其值。而且,在函数退出后,对它的任何引用(指向它的指针)都是无效的。如果函数范围内声明的变量是静态的,那么它将使变量不是自动变量,而是全局分配的变量。因此,变量将在函数退出后存在,从而在函数的调用中保持其值,并且即使在函数退出后,对它的任何引用(指针)也是有效的。注意,在这两种情况下,变量的作用域都只在该函数内,因此不可能从函数作用域之外直接(但只能通过保存的引用)访问它。

    静态所做的最后一件事是在运行变量的初始值设定项(即int foo=5)时进行更改。对于分配是全局的所有情况(除自动情况外的所有情况),初始值设定项在程序执行开始时只运行一次。它甚至在main()运行之前运行,因此如果初始值设定项不只是一个常量,而是运行一些代码,则可以得到一些不完全期望的结果。对于自动情况,每次输入函数时都会运行初始值设定项,在这种情况下,它始终在输入main()之后。

        4
  •  1
  •   Community CDub    7 年前

    我想补充一下南方饭店的回答 Static variables in C and C++

    以下备注:

    使用 static 用C++表示“本地到翻译单元”(HeRF==“HTTPS://RADS.STACKOFFROUT.COM/AMZN/CLICK/COM/020170.735”Re= =“NoFoLoLoNeFror”C++编程语言:特别版,附录B.2.3,不推荐的特征)。

    应改用未命名的命名空间:

    static int reply = 42; // deprecated
    
    namespace {
        int reply1 = 42;  // The C++ way
    }
    

    正如Southern Hospitality已经说过的,全局对象的初始化顺序是不确定的。在这种情况下,您应该考虑使用href=“http://en.wikipedia.org/wiki/singleton_pattern c.2b.2b”,singleton pattern。

    更新: GMAN评论了我的答案:

    “每一个翻译单位都定义了这个顺序……”:这真的让我不知所措,所以我用C++编程语言查找它。

    在第9.4.1节“非局部变量的初始化”中,stroustrup教授建议“返回引用的函数是全局变量的一个很好的替代方法”:

    int& use_count()
    {
            static int uc = 0;
            return uc;
    }
    

    “呼叫 use_count() 现在充当第一次使用时初始化的全局变量。例如:“

    void f()
    {
            std::cout << ++use_count() << '\n';
    }
    

    在我的理解中,这与单例模式非常相似。

    GMAN进一步评论道:“我们需要将创建这些对象的能力限制为一个,并提供对它的全局访问。”限制为一个真的与问题中的任何事情有关吗?我们可能需要一个全球性的,但谁能说我们不想在其他地方得到它呢?”

    一些引用自singleton(127)(gamma等人,设计模式):

    “单例模式是对全局变量的改进。它避免了使用存储唯一实例的全局变量污染名称空间。”

    “该模式使您很容易改变主意,并允许singleton类的多个实例。”

    按照第一次使用的顺序初始化单例。

    在Habor萨特,Andrei Alexandrescu,C++编码标准中,项目10表示:

    避免共享数据,尤其是全局数据。

    因此,我经常使用单例来避免全局数据。但是,当然,由于所有东西都是过度使用的,这可能是对单例模式的过度使用。(Johshua Kerievsky在他的书《重构到模式》中称之为“单色调主义”。)

    更新2:

    (很抱歉,但我不能写评论,因此无法更新。)

    贾夫在评论中写道:“四人帮在写关于单身模式的文章时吸烟是违法的。”

    显然,其他C++开发人员也会吸入有趣的物质。例如,Herb Sutter(他在第二个C++标准、C++0X的开发和微软的C++/CLI的首席架构师)担任了ISO C++标准委员会秘书和主席十多年。Habor目前是微软平台的PrISM内存模型的设计者和Visual C++并行编程的扩展,用C++编码标准编写,项目21:

    “当您需要这样一个(名称空间级别)变量,它可能依赖于另一个变量时,请考虑单例设计模式;小心使用,它可以通过确保在第一次访问时初始化对象来避免隐式依赖性。尽管如此,单胎是绵羊服装的一个全局变量,并被相互或循环依赖打破。”

    因此,如果可以,请避免使用全局数据。但是,如果必须在单独的翻译单元中使用全局数据,那么对于强制执行特定的初始化序列,singleton应该是一个可接受的解决方案。

    请注意,在Java语言中,全局数据甚至不存在。显然,全局数据被单例设计模式所取代/模拟。

    (我在JAVA工作中使用Java团队,我努力使我的C++程序与Java程序有最大的相似性。例如,每个类都位于自己的源文件/翻译单元中。)

        5
  •  0
  •   Ben Voigt    15 年前

    不是你的问题的直接答案,而是密切相关的东西,如果你同时使用C和C++的话。

    在C++中,与C不同的是,声明为“const”的全局变量在翻译单元中是隐式的,就像使用了“static”一样。

    例子:

    // file A
    extern const int glob;
    
    // file B
    const int glob = 42;
    

    如果你使用的是C编译器,而不是C++编译器。在C++中,文件B中的GROB变量不能从文件A中使用,链接器将产生“未解决的引用”错误。