不赞成使用static关键字…不再吗?


89

在C ++中,可以static在翻译单元中使用关键字来影响符号(变量或函数声明)的可见性。

在n3092中,已弃用:

附件D.2 [depr.static]
在命名空间范围内声明对象时,不建议使用static关键字(请参阅3.3.6)。

在n3225中,已将其删除。

我能找到的唯一的文章是有点非正式的。

它确实强调了,为了与C兼容(以及将C程序编译为C ++的能力),弃用是令人讨厌的。但是,直接将C程序编译为C ++可能会令人沮丧,因此我不确定是否值得考虑。

有谁知道为什么要更改?


3
您在C的命名空间范围内声明对象?
Etienne de Martel

呵呵,找到在哪里拿它了。试图删除评论,但您在那里打败了我。
Edward Strange


1
这也给C ++委员会提供了一个机会,可以在标准的下一版本中对某些东西进行预定义:-)
James McNellis 2011年

Answers:


75

C ++标准核心语言缺陷报告和已接受的问题中,修订版941012。不赞成使用静态`他们指出:

尽管7.3.1.1 [namespace.unnamed]声明不推荐使用static关键字在命名空间范围内声明变量,因为未命名的命名空间提供了更好的选择,但在可预见的将来不太可能删除该功能。 。

基本上说,弃用static并没有任何意义。它永远不会从C ++中删除,它仍然很有用,因为如果您只想声明具有内部链接的函数或对象,则不需要使用未命名空间的样板代码。


2
好吧,过时似乎会鼓励人们改用未命名的名称空间,这将是一件好事。
2011年

1
@unaperson:如果没有其他原因,则因为未命名的名称空间提供了用于在其TU内部创建变量,常量,函数和类型的相同机制。static class ... ,OTOH,将无法使用。
2011年

2
@nbt:因为您不能使用静态符号作为模板参数,并且因为许多新手会发现使用static更容易,然后又不愿意尝试使用<functional>和<algorithm>等。只是一个快速的想法。
塞巴斯蒂安·马赫

2
“因为不需要不需要命名空间的样板代码”?什么是“样板代码”?除“ namespace {”和“ }”之外还有其他内容吗?
towi 2014年

1
@ErikAronesty如果在另一个具有相同名称的文件中有一个“本地类”,则将犯ODR违规。
LF

32

我将尝试回答您的问题,尽管这是一个古老的问题,并且看起来并不十分重要(它本身并不是很重要),并且已经收到了很好的答案。我要回答的原因是,当语言基于现有语言,它与标准演变和语言设计的基本问题有关:应何时以不兼容的方式弃用,删除或更改语言功能?

在C ++中,可以在翻译单元中使用static关键字来影响符号(变量或函数声明)的可见性。

实际的联系。

在n3092中,已弃用:

弃用表示:

  • 意图,以消除在未来的某个功能; 这并不意味着不赞成使用的功能将在下一个标准修订版中删除,或者必须“很快”删除或完全删除。并且在下一个标准修订版中可能会删除不推荐使用的功能。
  • 阻止它使用的正式尝试。

后一点很重要。尽管从来没有正式的承诺说您的程序不会被下一个标准破坏,有时会无声地被打破,但是委员会应该设法避免破坏“合理的”代码。弃用应该告诉程序员,依赖某些功能是不合理的

它确实强调了,为了与C兼容(以及将C程序编译为C ++的能力),弃用是令人讨厌的。但是,直接将C程序编译为C ++可能会令人沮丧,因此我不确定是否值得考虑。

保留C / C ++通用子集非常重要,尤其是对于头文件而言。当然,static全局声明是具有内部链接的符号声明,这在头文件中不是很有用。

但是问题不仅仅在于与C的兼容性,还在于与现有C ++的兼容性:存在大量使用static全局声明的现有有效C ++程序。这段代码不仅形式上合法,而且听起来很合理,因为它按照预期的方式使用了定义良好的语言功能

仅仅因为现在有“更好的方法”(根据某些方法)来做某事,并不会使程序以旧的方式编写为“坏”或“不合理”。static在C和C ++社区中,对在全局范围内的对象和函数的声明中使用关键字的能力已广为人知,并且最常被正确使用。

同样,我不会因为“ C样式转换不好”而将C样式转换更改doublestatic_cast<double>,因为static_cast<double>添加了零信息和零安全性。

只要发明了一种新的做事方式,所有程序员都急于重写其现有的定义良好的工作代码这一想法真是太疯狂了。如果要消除所有继承的C丑陋和问题,而无需更改C ++,则可以发明一种新的编程语言。减少一半使用static几乎不会减少C ++的丑陋程度。

代码更改需要理由,而“老是坏”绝不是代码更改的理由。

打破语言变化需要非常有力的理由。使语言稍微简单一点绝不是进行重大更改的理由。

给出为什么static不好的原因非常明显,甚至不清楚为什么不同时弃用对象和函数声明-给它们不同的处理几乎不会使C ++更简单或更正交。

所以,真的,这是一个悲伤的故事。不是因为它带来的实际后果:它的实际后果是零。但这是因为它明显缺乏ISO委员会的常识。


5
正如您自己指出的那样,不建议使用它的目的是阻止其使用。但是,您没有理由反对阻止其使用是错误的。我当然希望没人能鼓励人们在匿名命名空间上使用命名空间范围的静态声明。不除非它们特别需要交叉编译C.
尼科尔流星锤

2
我不太在乎使用全局范围static或匿名命名空间的人,我也不鼓励也不劝阻。我的观点是,如果您真的想劝阻人们使用匿名名称空间,则必须给他们很好的论据。实际上,我相信在大多数实现中,在未命名的名称空间中声明的实体都是使用随机名称导出的符号,从而增加了导出表。声明为staticOTOH的实体不会以任何方式导出。因此,许多人根据该观察结果选择使用static
curiousguy 2011年

2
正如您自己指出的那样,弃用它的目的是阻止其使用。 ”阻止其使用的目的是,有一天它可能会消失。我的观点是,命名空间范围static永远不会消失,因此弃用它是错误的。“但是,您没有说服劝阻它的使用是错误的。 ”我还没有看到令人信服的论点,表明使用namespace-scopestatic是“错误的”。仅仅为了阻止其使用而弃用它是错误的,因为没有人真正相信它会消失,并且因为它没有说服人们使用它是“错误的”。
curiousguy 2011年

5
整个语言将“有一天消失”。让我们弃用C ++。
Lightness Races in Orbit

2
“类似地,我不会因为“ C样式转换不好”而将C样式强制转换为double改为static_cast <double>,因为static_cast <double>添加了零信息和零安全性。” 我与许多软件工程师的永恒斗争一直抱怨我随意使用C样式从一个原语到另一个原语。
Makogan

14

不论是否赞成,删除此语言功能都会破坏现有的代码并惹恼人们。

整个静态弃用只是沿着“匿名名称空间比静态更好”和“引用是更好的指针”的思路。大声笑。


1
“参考是更好的指针”?不,智能指针是更智能的指针。您不能将引用用于从堆,错误存储,免费存储中分配的内存。
丹·布雷斯劳

3
抱歉,我忘了以讽刺的笑脸结束它。
Maxim Egorushkin 2011年

2
@丹:这正是答案:“一厢情愿”,类似的错误思路。未命名的名称空间是一个重要功能,就像global-scope-static一样,尽管原因稍有不同,即使它们在适用性方面有些重叠。
Fred Nurk 2011年

@ Fred,@ Maxim:对不起,如果我误解了,或者我的记忆力有问题。但是,我不希望将“引用是更好的指针”归类为一厢情愿的情况,等同于“匿名名称空间比静态更好”。我很清楚尝试使后者坚持下去的尝试,但是我不记得有人提出过认真的建议以引用替换指针。再说一次,也许是我自己的意识缺失了。
丹·布雷斯劳

1
@DanBreslau:char* foo = new char; char& ref = *foo;只是因为最初给了您一个指针,所以您使用引用的能力一无所获。
Lightness Races in Orbit
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.