C 和 C++ 中的静态变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2528457/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Static variables in C and C++
提问by Naveen
Is there any difference between a variable declared as static
outside any function between C and C++. I read that static
means file scope and the variables will not be accessible outside the file. I also read that in C, global variables are static
. So does that mean that global variables in C can not be accessed in another file?
static
在 C 和 C++ 之间声明为任何函数之外的变量之间有什么区别。我读到这static
意味着文件范围和变量将无法在文件外部访问。我还读到在 C 中,全局变量是static
. 那么这是否意味着不能在另一个文件中访问 C 中的全局变量?
采纳答案by Eli Bendersky
No, there's no difference between C and C++ in this respect.
不,C 和 C++ 在这方面没有区别。
Read this SO answerabout what static
means in a C program. In C++ there are a couple of other meanings related to the use of static
for class variables (instead of instance variables).
阅读有关C 程序中含义的SO 答案static
。在 C++ 中,还有其他一些与static
for 类变量(而不是实例变量)的使用相关的含义。
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). From the point of view of visibility:
关于全局变量static
- 仅从内存分配的角度来看(它们被分配在数据段上,就像所有全局变量一样)。从能见度来看:
static int var; // can't be seen from outside files
int var; // can be seen from outside files (no 'static')
回答by Clifford
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.
在函数外部,关键字指的是链接,在函数内部指的是分配。函数外的所有变量都隐式地具有静态分配。也许是一个不幸的设计,但就是这样。
回答by Southern Hospitality
C and C++ are the same.
C 和 C++ 是相同的。
static does two different things.
静态做两件不同的事情。
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). 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.
对于在函数作用域之外声明的变量,它会更改变量的可见性(链接)。该变量将是一个全局变量,因为它在函数作用域之外。如果它不是静态的,它将具有通用链接(可见性),因此与此链接在一起的任何代码都可以访问它(他们可能必须将其声明为 extern)。如果变量在函数范围之外并且是静态的,它仍然是一个全局变量,因为它始终存在并保持其值,但同一编译单元(该 .c 文件和任何包含的 .h 文件)之外的任何代码都不能访问它。
For variables declared inside a function scope, static changes the location where the variable is stored. 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 (i.e. int foo = 5) for the variable is run. 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. 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.
当变量的初始化程序(即 int foo = 5)运行时,static 所做的最后一件事是更改。对于所有分配是全局的情况(除了自动分配的所有情况),初始化程序仅在程序执行开始时运行一次。它甚至在 main() 运行之前运行,因此如果您的初始化程序不仅仅是一个常量而是运行一些代码,您可以获得一些不太预期的结果。对于自动情况,每次输入函数时都会运行初始化程序,在这种情况下,它总是在输入 main() 之后。
回答by gh57.at
I want to add to Southern Hospitality's answer Static variables in C and C++
我想在Southern Hospitality 的答案中添加 C 和C++ 中的静态变量
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).
static
在 C++ 中不推荐使用来指示“本地到翻译单元”( href="https://rads.stackoverflow.com/amzn/click/com/0201700735" rel="nofollow noreferrer" The C++ Programming Language: Special Edition ,附录 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. In that situation, you should consider using the href="http://en.wikipedia.org/wiki/Singleton_pattern#C.2B.2B", Singleton pattern.
正如Southern Hospitality 已经说过的,全局对象的初始化顺序是未定义的。在这种情况下,您应该考虑使用 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()
now的调用充当在第一次使用时初始化的全局变量。例如:”
void f()
{
std::cout << ++use_count() << '\n';
}
In my understanding, this is very similar to the Singleton pattern.
在我的理解中,这与单例模式非常相似。
GMan commented further: "We need to limit our ability to create these objects to one, and provide global access to it." 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?"
GMan 进一步评论说:“我们需要将创建这些对象的能力限制为一个,并提供对其的全局访问。” 对一个的限制真的与问题中的任何内容有关吗?我们可能在全球范围内需要一个,但谁能说我们不想在其他地方使用它呢?”
Some quotes from Singleton(127) (Gamma et al, Design Patterns):
Singleton(127) 的一些引述(Gamma 等人,设计模式):
"The Singleton pattern is an improvement over global variables. It avoids polluting the name space with global variables that store sole instances."
“单例模式是对全局变量的改进。它避免了存储唯一实例的全局变量污染名称空间。”
"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. (Johshua Kerievsky calls this "Singletonitis" in his book "Refactoring to Patterns".)
因此我经常使用单例来避免全局数据。但是当然,由于一切都可以过度使用,这可能是对单例模式的过度使用。(Johshua Kerievsky 在他的“重构到模式”一书中称之为“单一性”。)
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. 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:
显然,其他 C++ 开发人员也吸了有趣的东西。例如,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."
“当您需要这样一个可能依赖于另一个的(命名空间级别)变量时,请考虑单例设计模式;小心使用,它可以通过确保在第一次访问时初始化对象来避免隐式依赖。不过,单例是一个全局变量羊的衣服,并被相互或循环依赖打破。”
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.
因此,如果可以,请避免使用全局数据。但是如果你必须在单独的翻译单元中使用全局数据,单例应该是一个可以接受的强制执行特定初始化序列的解决方案。
Note that in the Java language global data does not even exist. Obviously, global data is substituted/emulated by the use of the Singleton design pattern.
请注意,在 Java 语言中,全局数据甚至不存在。显然,全局数据是通过使用单例设计模式来替代/模拟的。
(For I am working in my dayjob with a Java team, I strive for a maximal similarity of my C++ programs with Java programs. E.g, every class is situated in its own source file/translation unit.)
(因为我在 Java 团队的日常工作中努力使我的 C++ 程序与 Java 程序最大程度地相似。例如,每个类都位于自己的源文件/翻译单元中。)
回答by Ben Voigt
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. In C++, the glob variable in file B cannot be used from file A and the linker will generate an "unresolved reference" error.
如果您使用的是 C 编译器而不是 C++ 编译器,这将起作用。在 C++ 中,文件 B 中的 glob 变量不能从文件 A 中使用,链接器将生成“未解析的引用”错误。