C++ 如何使用命名空间中的变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11478152/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:10:55  来源:igfitidea点击:

How to work with variable in namespace

c++staticnamespaces

提问by dsollen

I think I hvae a fundamental misunderstanding of namespace and/or static variable. But I have tried this test code (typed by hand, forgive typos)

我认为我对命名空间和/或静态变量存在根本性的误解。但是我试过这个测试代码(手工输入,请原谅错别字)

test.h:

测试.h:

namespace test{
   static int testNum=5;
   void setNum(int value);
}

main.cpp:

主.cpp:

#include <test.h>

int test::setNum(int value){
   testNum=value;
}

int main(){
    test::setNum(9);
    cout<<test::testNum;
}

when I run this I get the value 5, not 9 as I would have expected. It seems almost as if I have two instances of the testNum variable, but that seems to be the exact opposite of what static should be doing. I'm guessing I've made a mistake in assuming that these features were identical to their java equvilants somehow...

当我运行它时,我得到的值为 5,而不是我预期的 9。看起来好像我有两个 testNum 变量的实例,但这似乎与 static 应该做的完全相反。我猜我犯了一个错误,假设这些功能在某种程度上与它们的 Java 等效项相同......

I also get an error stating that testNum is declared multuple times if I remove the static from my declaration of testNum, could someone explain why that is the case as well?

如果我从 testNum 的声明中删除静态,我也会收到一个错误,指出 testNum 被多次声明,有人可以解释为什么会这样吗?

Thank you

谢谢

回答by Jonathan Wakely

First, your misunderstanding has nothingto do with namespaces, it's only about static. For the rest of this answer I'm going to refer to simply testNumbecause the fact it's in a namespace is irrelevant.

首先,您的误解与名称空间无关,仅与static. 对于这个答案的其余部分,我将仅参考它,testNum因为它位于命名空间中的事实无关紧要。

I'm also assuming you have another file, probably called test.cpp, which also includes test.hand defines the setNumfunction.

我还假设您有另一个文件,可能名为test.cpp,其中还包含test.h并定义了该setNum函数。

When a variable or function at namespace-scope (i.e. not a class member or local to a function) is declared staticit means the entity's name is internal to that file. Formally it has "internal linkage", meaning it can't be referred to by name or linked to from other files (it can be indirectly referred to through a pointer or by passing it as an argument to another function.) That means if several files define static int testNumthen each file has its own internal variable with that name, distinct from the testNumin every other file (in fact one file could have static int testnumand another could have static double testnumand another static char* testNum, they'd all be distinct and internal to each file.) If you put a definition like that in header then every file that includes the header has its own testNum.

当命名空间范围内的变量或函数(即不是类成员或函数的局部变量)被声明时,static这意味着实体的名称是该文件的内部名称。正式它具有“内部链接”,这意味着它不能通过名称引用或从其他文件链接(它可以通过指针间接引用或将其作为参数传递给另一个函数。)这意味着如果有几个文件定义static int testNum,然后每一个文件都有与该名称其自身的内部变量,从不同testNum的所有其他文件(实际上是一个文件可以有static int testnum和另一个可能有static double testnum和另一个static char* testNum,他们全是不同的和内部的每个文件。)如果您将这样的定义放在 header 中,然后每个包含 header 的文件都有自己的testNum.

So with staticon your variable in a header you have a differentvariable called testNumin every file that includes test.h. That means if you set testNumin one file and call a function in a different file which uses testNumit refers to a differentvariable, which just happens to have the same name.

因此,与static上一个头的变量,你有一个不同的叫做变量testNum在每一个包含文件test.h。这意味着如果您testNum在一个文件中设置并调用另一个文件中的函数,该函数使用testNum它引用不同的变量,而该变量恰好具有相同的名称。

Because of this, declaring non-const staticvariables in headers is almost always wrong.

因此,static在标头中声明非常量变量几乎总是错误的。

Without staticyou would have a definition of the testNumvariable in every file that includes test.h, which is not allowed: every entity must be defined once and once only in your program. The way to solve that is to declarethe variable in the header, but not defineit, which you do by telling the compiler the variable is extern:

如果没有,static您将testNum在每个包含 的文件中定义变量test.h,这是不允许的:每个实体必须在您的程序中一次又一次地定义。解决这个问题的方法是在头文件中声明变量,但不定义它,你通过告诉编译器变量是extern

extern int testNum;  // N.B. no "= 1" here

That tells the compiler there is a variable with "external linkage" called testNum, so when code refers to testNumit will always mean the same variable (not some name with internal linakge that is a different entity in every file.) After declaring an externvariable it is your responsibility to ensure there is exactly one definition provided somewhere in the program, so in exactly onefile (i.e. not in a header that gets included in multiple files) you define it:

这告诉编译器有一个名为“外部链接”的变量testNum,因此当代码引用testNum它时,它总是意味着相同的变量(不是某个具有内部链接的名称,它是每个文件中的不同实体。)声明extern变量后,它是您有责任确保在程序中的某处恰好提供了一个定义,因此在一个文件中(即不在包含在多个文件中的头文件中)您定义它:

int testNum = 1;

回答by James Kanze

staticat namespace scope is a misnomer, and shouldn't be used. It means simply that the entity declared static has internal name binding; in other words, that the same name in other translation units will refer to a different entity, and in the case of variable definitions, that there will be a separate instance of the variable in each translation unit. It has no effect on lifetime. (Allvariables declared or defined at namespace scope have static lifetime.)

static在命名空间范围内用词不当,不应使用。这意味着声明为 static 的实体具有内部名称绑定;换句话说,其他翻译单元中的相同名称将指代不同的实体,并且在变量定义的情况下,每个翻译单元中将有一个单独的变量实例。它对寿命没有影响。(在命名空间范围内声明或定义的所有变量都具有静态生命周期。)

staticat namespace scope is also deprecated. Don't use it.

static在命名空间范围内也已弃用。不要使用它。

With regards to declaring a variable in a header: prefix it with extern, and not static. If a variable is declared extern, and there is no initialization, the declaration is not a definition. Of course, in this case, you must provide a definition somewhere (in a single source file). Something along the lines of:

关于在标头中声明变量:前缀为 extern, 而不是static。如果声明了变量extern,并且没有初始化,则声明不是定义。当然,在这种情况下,您必须在某处(在单个源文件中)提供定义。类似的东西:

extern int testNum = 5;
int testNum = 5;
int testNum;          //  implicitly initialized with 0.

EDIT:

编辑:

To clarify somewhat: there is some confusion here between lifetime and name binding:

澄清一下:生命周期和名称绑定之间存在一些混淆:

  • an object has a lifetime (auto, static or dynamic—or temporary, or exception), and
  • a name is bound to an entity; if the name is declared to be a variable, the entity is an object.
  • 对象具有生命周期(自动、静态或动态——或临时或异常),并且
  • 名称绑定到一个实体;如果名称被声明为变量,则实体是一个对象。

Do notconfuse the keyword staticwith static lifetime. (Functions can be static, but functions have no defined lifetime in C++; they're just there.)

千万不能混淆的关键词static静态寿命。(函数可以是static,但函数在 C++ 中没有定义的生命周期;它们就在那里。)

The rules regarding these are not very orthognal. Basically, with regards to lifetime:

关于这些的规则不是很正交。基本上,关于生命周期:

  • all variables declared at namespace scope have static lifetime, always,
  • variables declared at local scope have auto lifetime unlessthey are declared static, and
  • variables declared at class scope have the lifetime of the class object which contains them, unless they are declared static. regards to lifetime.
  • 在命名空间范围内声明的所有变量都具有静态生命周期,始终,
  • 在局部范围内声明的变量具有自动生存期,除非它们被声明static,并且
  • 在类范围内声明的变量具有包含它们的类对象的生命周期,除非它们被声明static。关乎一生。

Objects with static lifetime come into being sometime before main, and live until after you return from main.

具有静态生命周期的对象在某个时间之前出现main,并一直存在到您从main.

With regards to name binding:

关于名称绑定:

  • variables declared at namespace scope have external name binding, unless they are declared static, in which case they have internal name binding (but this use of staticis deprecated), or if they are const, and are not declared extern,
  • variables declared at class scope have external name binding, even if they are declared static, and
  • variables declared at block scope have no binding.
  • 在命名空间范围内声明的变量具有外部名称绑定,除非它们被声明static,在这种情况下它们具有内部名称绑定(但static不推荐使用 ),或者如果它们是 const,并且未声明extern
  • 在类范围内声明的变量具有外部名称绑定,即使它们被声明static,并且
  • 在块范围内声明的变量没有绑定。

Finally, there is the question of whether a declaration is a definition or not. If it is a definition, memory is allocated and the object is (or may be) initialized. If it is not a definition, it simply tells the compiler that there is a definition somewhere else for the entity (object) declared in the declaration. In general, a variable declaration is a definition unlessit is declared externand does nothave an initializer.

最后,还有一个声明是否是定义的问题。如果是定义,则分配内存并初始化(或可能)对象。如果它不是定义,它只是告诉编译器在声明中声明的实体(对象)在其他地方有一个定义。一般情况下,一个变量声明是一个定义,除非它被声明extern并没有 有初始值。

回答by Adam

You might want to make sure your code actually has problems before you post it asking what's wrong ;)

在发布之前,您可能想确保您的代码确实有问题,询问出了什么问题;)

I copy/pasted and fixed your typos, and manually did the include:

我复制/粘贴并修复了您的错别字,并手动完成了包括:

#include <iostream>
using namespace std;

namespace test{
   static int testNum=5;
   void setNum(int value);
}

void test::setNum(int value){
   testNum=value;
}

int main(){
    test::setNum(9);
    cout<<test::testNum;
}

result:

结果:

$ ./a.out 
9

What you haven't said is what else is in your program. If you have more than just main.cpp, and include your test.h, then each .cpp file will have its own copy of testNum. If you want them to share then you need all but one to mark it as extern.

你没有说的是你的程序中还有什么。如果您不仅有 main.cpp,而且包含您的 test.h,那么每个 .cpp 文件都将拥有自己的 testNum 副本。如果您希望他们共享,那么您需要将其标记为extern.