在C++中,可以使用翻译单元中的EDCOX1×0关键字来影响符号的可见性(变量或函数声明)。
在N3092中,这已被弃用:
Annex D.2 [depr.static]
The use of the static keyword is deprecated when declaring objects in namespace scope (see 3.3.6).
在N3225中,已将其移除。
我能找到的唯一一篇文章有点非正式。
但它确实强调了,与C兼容(以及编译C程序作为C++的能力),这种厌恶是令人讨厌的。然而,编译一个C程序直接作为C++已经是一个令人沮丧的经验,所以我不确定它是否值得考虑。
有人知道为什么会改变吗?
- 在C中的名称空间范围内声明对象?
- 嘿,THX,在哪儿找到了。试图删除评论,但你在那里打败了我。
- 问题来自stackoverflow.com/questions/4725204/…
- 这也给C++委员会提供了在下一版本标准中解开某些东西的机会:
- stackoverflow.com/questions/4422507/…
- @马丁巴:是的……?
- @ MatthieuM。-对不起,我只是觉得这个问题应该链接到这里(不远),所以我把链接放到评论中了。
- @ MartinBa:啊!好吧,我以为你想问一些问题,但不知何故按回车键太快了,但一个小时后没看到这个问题,我很惊讶:)
- 标准委员会认为,为什么匿名名称空间不能充分替代静态名称空间?
- @Matthieum:在上面的文章中,有一些客观的答案可以回答您的问题,当未命名的名称空间不起作用时,说明所有static的工作位置;这里的答案主要是基于opinon的。
在C++标准的核心语言缺陷报告和可接受的问题,修订版94下1012。他们注意到:
Although 7.3.1.1 [namespace.unnamed] states that the use of the static keyword for declaring variables in namespace scope is deprecated because the unnamed namespace provides a superior alternative, it is unlikely that the feature will be removed at any point in the foreseeable future.
基本上说,static的贬值并没有真正意义。它永远不会从C++中移除,它仍然是有用的,因为如果您想声明一个具有内部链接的函数或对象,则不需要使用未命名的命名空间所需的样板代码。
- 谢谢你的链接,没有考虑过缺陷:/
- 嗯,这种贬低似乎会鼓励人们使用未命名的名称空间,这是一件好事。
- @为什么这会是件好事?
- @unperson:如果没有其他原因,那么因为未命名的名称空间提供了使变量、常量、函数和类型成为其tu内部的相同机制。static class ... otoh将不起作用。
- @NBT:因为你不能用静态符号作为模板参数,而且很多新手会发现静态符号更容易使用,然后就不用尝试了。只是个简单的想法。
- "因为您不需要未命名名称空间所需的样板代码"?什么"样板文件代码"?除了"EDOCX1"(1)和"EDOCX1"(2)之外?
- @towi与static相比,有两个附加的大括号,在许多编码样式上,您将编写至少3行代码来缩进声明。
- 我喜欢将helper函数、globals等声明为静态的,并且尽可能接近它们的用法。为此,名称空间语法很难看,"static"很好。其他人喜欢把他们所有的助手都放在一个文件的顶部。命名空间语法在这里更有用。所以这是一个风格问题。它们最终是等效的。
- @短语不是"静态"类/typedef之类的东西。文件中的本地类在该文件之外不可用。所以不需要在它们周围使用名称空间。仅限不与模板冲突的函数(可以始终是静态的)和全局函数。
- 更不用说他们只谈论被移除部分的对象,这本身就是愚蠢的。功能呢?这次搬迁得到了我全心全意的赞同。
我会尽力回答你的问题,虽然这是一个古老的问题,看起来不太重要(它本身并不十分重要),而且它已经收到了相当好的答案。我之所以要回答这个问题,是因为当语言基于现有语言时,它涉及到标准演进和语言设计的基本问题:什么时候应该不推荐、删除或以不兼容的方式更改语言功能?
In C++ it is possible to use the static keyword within a translation unit to affect the visibility of a symbol (either variable or function declaration).
实际上是连接。
In n3092, this was deprecated:
折旧表示:
- 将来删除某些功能的意图;这并不意味着不推荐使用的功能将在下一个标准版本中删除,也不意味着它们必须"很快"删除,或者完全删除。在下一个标准版本中,可以删除不推荐使用的功能。
- 阻止使用的正式尝试。
后一点很重要。虽然从来没有正式的承诺,你的程序不会被破坏,有时是无声的,以下一个标准,委员会应该尽量避免破坏"合理"的代码。贬义应该告诉程序员依赖某些特性是不合理的。
It does underline though, that for compatibility with C (and the ability to compile C-programs as C++) the deprecation is annoying. However, compiling a C program directly as C++ can be a frustrating experience already, so I am unsure if it warrants consideration.
保存C/C++公共子集是非常重要的,特别是对于头文件。当然,static全局声明是具有内部链接的符号声明,这在头文件中不太有用。
但是这个问题绝不仅仅是与C的兼容性,它与现有C++的兼容性:有大量现存的有效的C++程序使用EDCOX1×0的全局声明。这段代码不仅是正式的合法代码,而且是合理的,因为它使用了一种定义良好的语言特性,即其预期的使用方式。
仅仅因为现在有一种"更好的方法"(根据一些人的说法)来做一些事情,并不会使程序写的老方法"坏"或"不合理"。在C和C++社区中,在全局范围内使用对象的EDCOX1"0"关键字的能力是很好理解的,并且最常用的是正确的。
同样,我不打算仅仅因为"C-style casts不好",就将C-style casts改为double改为static_cast,因为static_cast增加了零信息和零安全性。
每当一种新的方法被发明出来,所有的程序员都会争先恐后地重写他们现有的定义良好的工作代码,这种想法简直是疯了。如果你想删除所有继承的C丑陋和问题,你不改变C++,你发明了一种新的编程语言。半删除一个EDCOX1(0)的用法几乎不会使C++的C难看。
代码更改需要理由,"旧的是坏的"永远不是代码更改的理由。
打破语言变化需要强有力的理由。使语言变得非常简单永远不是一个突破性改变的理由。
为什么EDOCX1 0的坏原因是非常弱的,甚至不清楚为什么不把对象声明和函数声明放在一起——给予它们不同的处理几乎不能使C++更简单或更正交。
所以,真的,这是一个悲伤的故事。不是因为它有实际的后果:它没有实际的后果。但因为它显示出明显缺乏ISO委员会的常识。
- 正如你自己所指出的,贬低它的目的是阻止它的使用。然而,你并没有提出反对使用它是错误的。我当然希望没有人鼓励人们在匿名名称空间上使用名称空间范围的静态声明。除非他们特别需要交叉编译C。
- 我不太关心使用全局范围static或匿名名称空间的人,我也不鼓励或气馁。我的观点是,如果你真的想劝阻人们使用匿名名称空间,你必须给他们一个很好的理由。在实践中,我相信在大多数实现中,在未命名的名称空间中声明的实体都是以随机名称导出的符号,从而增加了导出表。声明为static的实体,Otoh,不以任何方式出口。因此,许多人根据观察结果选择使用static。
- "正如你自己所指出的,贬低它的目的是阻止它的使用。"贬低它的目的是它有一天可能会消失。我的观点是,名称空间范围static永远不会消失,因此不使用它是错误的。"然而,你没有提出反对使用它是错误的论点,"我没有看到任何令人信服的论据表明使用命名空间范围static是"错误的"。贬低它只是为了阻止它的使用是错误的,因为没有人真的相信它会消失,而且因为它不能说服人们使用它是"错误的"。
- "我当然希望没有人鼓励人们在匿名命名空间上使用命名空间范围的静态声明。"一些人认为static更好,并鼓励它在匿名命名空间上使用。我的观点不是两个都比另一个好;我的观点是1)没有任何功能(static,anon名称空间)是"错误的"。2)贬低一个有用的、定义明确的、广泛使用的功能是错误的。这样做降低了C++委员会的可信度(而且已经很低了)。
- 整个语言"总有一天会消失"。让我们贬低C++。
- @像Fortran那样的非停站时间旅行?(什么时候?)你应该知道,作为一个时间旅行者。和COBOL?
- @好奇心的家伙:他们还没有,这完全证明不了什么!
- @NicolaBolas不仅仅是我:CWG(核心工作组)投票表决"匿名名称空间不足以替代功能"。参见N3296
不管是否已弃用,删除此语言功能将破坏现有代码并使人恼火。
整个静态贬低的事情只是一厢情愿地沿着"匿名名称空间比静态名称空间更好"和"引用是更好的指针"的路线思考。大声笑.
- "参考是更好的指针"?不,智能指针是更智能的指针。不能对从堆中分配的内存使用引用,err,free store。
- 对不起,我忘了用讽刺的微笑结束它。
- @丹:这正是这个答案所说的:"一厢情愿"沿着一条类似的错误思路。未命名的名称空间是一个重要的特性,正如全局范围静态的一样,尽管原因略有不同,而且即使它们在适用性上有一些重叠。
- @弗雷德,@maxim:对不起,如果我误解了,或者我的记忆有问题。但我并不将"引用是更好的指针"归类为等同于"匿名名称空间比静态名称空间更好",这是一种一厢情愿的想法。我很清楚试图让后者坚持下来,但我不记得有人认真提议用引用来替换指针。再说一遍,也许是我自己的意识不足。
- @丹:我偶尔也会看到有人在这样或其他地方试图推动"参考是更好的指针",但这当然没有认真努力把它从另一个人的语言中删除。我认为你只是误解了,因为我看不出马克西姆自己也曾坚持过。耸耸肩*
- @弗雷德·纽克,@maxim:好吧,那是(至少有一个地方)我们断绝联系的地方:我不是想说maxim自己提出了这个主张。他的文章中的引述使我明白他是在引用第三方的话。我的全部意图是质疑是否有任何重要的第三方曾提出过一个严肃的主张,即"参考是更好的指针",因为我不知道怎么会有人开始提出这种情况。(我想他们在这里发生的时候我错过了这样的讨论。)也许我应该说"一个人不能使用引用…",而不是"你不能使用引用…"。
- @丹布雷斯劳:埃多克斯1〔3〕那为什么?
- @在轨道上的亮度竞赛:也就是说,如果foo是一个参照物,你不能做像char &foo = new char;这样的事情,当然也不能做delete foo;。
- @Danbreslau:char* foo = new char; char& ref = *foo;,仅仅因为你得到了一个指针,最初对你使用引用的能力没有任何影响。
- 一个引用总是依赖于另一个变量(可以这样说:—);不能用引用变量替换指针。(实际上,我怀疑您可以,但它需要一些非常丑陋的黑客,这些黑客可能依赖于实现。)