简体   繁体   English

C和C ++中的静态变量

[英]Static variables in C and C++

Is there any difference between a variable declared as static outside any function between C and C++. 在C和C ++之间的任何函数之外声明为static的变量之间是否有任何区别。 I read that static means file scope and the variables will not be accessible outside the file. 我读到static意味着文件范围,并且文件外部不能访问变量。 I also read that in C, global variables are static . 我还读到在C中,全局变量是static So does that mean that global variables in C can not be accessed in another file? 那么这是否意味着C中的全局变量无法在另一个文件中访问?

No, there's no difference between C and C++ in this respect. 不,在这方面C和C ++没有区别。

Read this SO answer about what static means in a C program. 阅读这个关于C程序中static含义的答案 In C++ there are a couple of other meanings related to the use of static for class variables (instead of instance variables). 在C ++中,还有一些与使用static类变量(而不是实例变量)相关的其他含义。

Regarding global vars being static - only from the point of view of memory allocation (they are allocated on the data segment, as all globals are). 关于全局变量是static - 仅从内存分配的角度来看(它们被分配在数据段上,就像所有全局变量一样)。 From the point of view of visibility: 从可见性的角度来看:

static int var;    // can't be seen from outside files
int var;           // can be seen from outside files (no 'static')

There are two concepts here "static linkage (or scope)" and static allocation ". 这里有两个概念“静态链接 (或范围)”和静态分配 “。

Outside a function the keyword refers to linkage, inside it refers to allocation. 在函数外部,关键字指的是链接,里面指的是分配。 All variables outside a function have static allocation implicitly. 函数外的所有变量都隐式地具有静态分配。 An unfortunate design perhaps, but there it is. 也许是一个不幸的设计,但确实如此。

C and C++ are the same. C和C ++是一样的。

static does two different things. static做了两件不同的事情。

For variables declared outside a function scope, it changes the visibility (linkage) of the variable. 对于在函数作用域外声明的变量,它会更改变量的可见性(链接)。 The variable will be a global variable since it is outside a function scope. 变量将是一个全局变量,因为它在函数范围之外。 If it isn't static, it will have universal linkage (visibility) so any code linked together with this can access it (they may have to declare it extern). 如果它不是静态的,它将具有通用链接(可见性),因此与此链接在一起的任何代码都可以访问它(它们可能必须将其声明为extern)。 If the variable is outside a function scope and is static, it still a global variable in that it always exists and keeps its value, but no code outside the same compilation unit (that .c file and any .h's included) can access it. 如果变量在函数作用域之外并且是静态的,它仍然是一个全局变量,因为它始终存在并保持其值,但是在同一编译单元(.c文件和包含的任何.h)之外的代码都不能访问它。

For variables declared inside a function scope, static changes the location where the variable is stored. 对于在函数作用域内声明的变量,static会更改存储变量的位置。 If it is not static, it will be an automatic variable, that means it disappears as the function exits and comes back into existence (on the stack) when the function is entered again. 如果它不是静态的,它将是一个自动变量,这意味着它会随着函数的退出而消失,并在再次输入函数时重新出现(在堆栈中)。 This it loses its value when you exit the function. 退出函数时它会丢失它的值。 And also any references to it (pointers to it) are invalid after the function exits. 并且在函数退出后,对它的任何引用(指向它)都是无效的。 If a variable declared inside a function scope is static, then it makes it not an automatic variable but a globally allocated one. 如果在函数作用域内声明的变量是静态的,那么它使它不是自动变量而是全局分配的变量。 So the variable will exist after the function exits and thus will keep its value across invocations of the function and also any references (pointers) to it are valid even after the function exits. 因此,变量将在函数退出后存在,因此将在函数的调用中保持其值,并且即使在函数退出之后,对它的任何引用(指针)也是有效的。 Note that in both cases the scope of the variable is only within that function so it's not possible to access it directly (but only via saved reference) from outside the function scope. 请注意,在这两种情况下,变量的范围仅在该函数内,因此无法从函数范围外直接访问它(但仅通过保存的引用)。

One last thing static does is change when the initializer (ie int foo = 5) for the variable is run. 静态做的最后一件事是在运行变量的初始值设定项(即int foo = 5)时进行更改。 For all the cases where the allocation is global (every case except the automatic one), the initializer is run only once, at the beginning of the execution of your program. 对于分配是全局的所有情况(除了自动分配之外的每种情况),初始化程序仅在程序执行开始时运行一次。 It is run before main() is run even, so you can get some not quite expected result if your initializer isn't just a constant number but runs some code. 它在main()运行之前运行,因此如果初始化程序不仅仅是一个常数而是运行一些代码,那么你可以得到一些不太理想的结果。 For the automatic case, the initializer is run every time the function is entered, and in this case it is always after main() has been entered. 对于自动情况,每次输入函数时都会运行初始化程序,在这种情况下,它始终在输入main()之后运行。

I want to add to Southern Hospitality's answer Static variables in C and C++ 我想在C和C ++中添加Southern Hospitality的回答静态变量

the following remarks: 以下评论:

The use of static to indicate "local to translation unit" is deprecated in C++ ( href="https://rads.stackoverflow.com/amzn/click/com/0201700735" rel="nofollow noreferrer" The C++ Programming Language: Special Edition, Appendix B.2.3, Deprecated Features). 在C ++中不推荐使用static来表示“本地到翻译单元”(href =“https://rads.stackoverflow.com/amzn/click/com/0201700735”rel =“nofollow noreferrer”C ++编程语言:特殊版本,附录B.2.3,不推荐使用的功能)。

You should use unnamed namespaces instead: 您应该使用未命名的命名空间:

static int reply = 42; // deprecated

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

As already said by Southern Hospitality, the order of initialization of global objects is undefined. 正如Southern Hospitality所说,全局对象的初始化顺序是不确定的。 In that situation, you should consider using the href="http://en.wikipedia.org/wiki/Singleton_pattern#C.2B.2B", Singleton pattern. 在这种情况下,您应该考虑使用单点模式的href =“http://en.wikipedia.org/wiki/Singleton_pattern#C.2B.2B”。

UPDATE: GMan commented my answer: 更新:GMan评论我的回答:

"The order is defined per-translation unit, ...": This really slipped my mind, so I looked it up in The C++ Programming Language. “订单是按翻译单位定义的,......”:这真的让我不知所措,所以我在C ++编程语言中查了一下。

In Section 9.4.1, Initialization of Non-local Variables, Prof. Stroustrup suggests that "a function returning a reference is a good alternative to a global variable": 在第9.4.1节“非局部变量的初始化”中,Stroustrup教授建议“返回引用的函数是全局变量的一个很好的替代”:

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

"A call to use_count() now acts as a global variable that is initialized at its first use. For example:" “对use_count()调用现在充当首次使用时初始化的全局变量。例如:”

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

In my understanding, this is very similar to the Singleton pattern. 据我所知,这与Singleton模式非常相似。

GMan commented further: "We need to limit our ability to create these objects to one, and provide global access to it." GMan进一步评论说:“我们需要限制我们创建这些对象的能力,并提供对它的全局访问。” Does the limiting to one really relate to anything in the problem? 对一个人的限制是否真的与问题中的任何事情有关? We may need one globally, but who's to say we don't want it in other places?" 我们可能需要全球一个,但是谁说我们不想在其他地方使用它?“

Some quotes from Singleton(127) (Gamma et al, Design Patterns): Singleton(127)(Gamma等,Design Patterns)的一些引用:

"The Singleton pattern is an improvement over global variables. It avoids polluting the name space with global variables that store sole instances." “Singleton模式是对全局变量的改进。它避免了使用存储唯一实例的全局变量来污染名称空间。”

"The pattern makes it easy to change your mind and allow more than one instance of the Singleton class." “这种模式可以让你轻松改变主意,并允许使用Singleton类的多个实例。”

Singletons are initialized in the order they are first used. 单身人士按照他们第一次使用的顺序进行初始化。

In Herb Sutter, Andrei Alexandrescu, C++ Coding Standards, Item 10 says: 在Herb Sutter,Andrei Alexandrescu,C ++编码标准中,第10项说:

"Avoid shared data, especially global data." “避免共享数据,尤其是全球数据。”

Therefore I use often Singletons to avoid global data. 因此,我经常使用单身人士来避免全球数据。 But of course, as everything is overusable, this could be a overuse of the Singleton pattern. 但是,当然,由于一切都是可以过度使用的,这可能是过度使用Singleton模式。 (Johshua Kerievsky calls this "Singletonitis" in his book "Refactoring to Patterns".) (Johshua Kerievsky在他的“Refactoring to Patterns”一书中称之为“单身性炎症”。)

UPDATE 2: 更新2:

(Sorry, but I cannot write comments, therefore this Update.) (对不起,但我不能写评论,因此这个更新。)

Jalf wrote in his comment: "The gang of four were smoking something illegal when they wrote about the singleton pattern." 贾尔夫在评论中写道:“当他们撰写有关单身人士模式的文章时,四人帮在吸食非法行为。”

Obviously, other C++ developers smoked interesting substances, too. 显然,其他C ++开发人员也吸食了有趣的物质。 For example, Herb Sutter (he served for over a decade as secretary and chair of the ISO C++ standards committee during the development of the second C++ standard, C++0x, and as lead architect of C++/CLI at Microsoft. Herb is currently the designer of the Prism memory model for Microsoft platforms and the Concur extensions to Visual C++ for parallel programming), wrote in C++ Coding Standards, Item 21: 例如,Herb Sutter(他在第二个C ++标准,C ++ 0x开发期间担任ISO C ++标准委员会秘书和主席十多年,并在Microsoft担任C ++ / CLI的首席架构师.Herb目前用于Microsoft平台的Prism内存模型的设计者和用于并行编程的Visual C ++的Concur扩展,在C ++编码标准中写道,第21项:

"When you need such a (namespace level) variable that might depend upon another, consider the Singleton design pattern; used carefully, it might avoid implicit dependencies by ensuring that an object is initialized upon first access. Still, Singleton is a global variable in sheep's clothing, and is broken by mutual or cyclic dependencies." “当你需要一个可能依赖于另一个的(命名空间级别)变量时,请考虑Singleton设计模式;仔细使用它可以通过确保在第一次访问时初始化对象来避免隐式依赖。但是,Singleton是一个全局变量绵羊的衣服,被相互或循环的依赖打破。“

So, avoid global data, if you can. 因此,如果可以,请避免使用全局数据。 But if you have to use global data in separate translation units, Singleton should be an acceptable solution for enforcing a specific initialization sequence. 但是,如果必须在单独的转换单元中使用全局数据,则Singleton应该是可执行特定初始化序列的可接受解决方案。

Note that in the Java language global data does not even exist. 请注意,在Java语言中,全局数据甚至不存在。 Obviously, global data is substituted/emulated by the use of the Singleton design pattern. 显然,使用Singleton设计模式替代/模拟全局数据。

(For I am working in my dayjob with a Java team, I strive for a maximal similarity of my C++ programs with Java programs. Eg, every class is situated in its own source file/translation unit.) (因为我在Java团队的日常工作中工作,我努力使我的C ++程序与Java程序最大程度地相似。例如,每个类都位于其自己的源文件/翻译单元中。)

Not really a direct answer to your question, but something closely related to watch out for if you use both C and C++. 对你的问题不是一个直接的答案,但如果你同时使用C和C ++,那么要注意与之密切相关。

In C++, unlike C, global variables which are declared "const" are implicitly local to the translation unit, AS IF "static" had been used. 在C ++中,与C不同,声明为“const”的全局变量对于转换单元是隐式本地的,因为AS IF使用了“静态”。

Example: 例:

// file A
extern const int glob;

// file B
const int glob = 42;

This will work if you are using a C compiler but not with a C++ compiler. 如果您使用C编译器但不使用C ++编译器,这将起作用。 In C++, the glob variable in file B cannot be used from file A and the linker will generate an "unresolved reference" error. 在C ++中,文件B中的glob变量不能在文件A中使用,链接器将生成“未解析的引用”错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM