什么时候适合在 C++ 中使用静态(在未命名的命名空间上)?
我一整天都在阅读有关未命名命名空间的文章,大多数文章都解释了何时应该在 static 关键字上使用未命名命名空间。但我仍然有一个大问题什么时候适合使用静态?毕竟它还没有完全弃用,那么带有静态函数的头文件我现在应该将它们放入未命名的命名空间中吗?
#ifndef HEADER_H
#define HEADER_H
static int func() {
...
}
// versus:
namespace {
int func() {
...
}
};
#endif // HEADER_H
或者静态成员函数呢?
问候
I have been reading articles about unnamed namespaces the whole day, most articles explained when you should use unnamed namespaces over the static keyword. But I am still left with one big question when is it appropriate to use static? After all it is not completely deprecated, what about header files with static functions should I put them into unnamed namespaces now?
#ifndef HEADER_H
#define HEADER_H
static int func() {
...
}
// versus:
namespace {
int func() {
...
}
};
#endif // HEADER_H
Or what about static member functions?
Greetings
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
该标准的准确措辞是:
头文件中的函数应该是内联的,而不是静态的或位于未命名的命名空间中。
inline
意味着您在程序中最多只会得到该函数的一个副本,而其他方法将为您提供包含标头的每个文件的单独副本。除了膨胀之外,如果函数包含函数静态数据,这可能会导致错误的行为。 (编辑:除非函数在不同的编译单元中应该有不同的定义,可能是由于在包含头文件之前定义了不同的预处理器宏。在这种情况下,最好的方法是不包含它根本不用,而是用木桩将其埋在一个没有标记的坟墓中。)除了常量之外,数据对象通常根本不应该在头文件中定义,而只能声明
extern
。静态成员函数是另一回事,你必须在那里使用
static
,因为没有其他方法来声明它们。该用法并未被弃用,因为它不在命名空间范围内。更新: C++11 已删除了弃用内容,因此不再有任何特殊原因比
static
更喜欢未命名命名空间。但是你仍然不应该在头文件中使用它们,除非你正在做一些奇怪的事情。The precise wording of the standard is:
Functions in a header file should be
inline
rather thanstatic
or in an unnamed namespace.inline
means you will only end up with at most one copy of the function in your program, while the other methods will give you a separate copy from each file that includes the header. As well as bloat, this could give incorrect behaviour if the function contains function-static data. (EDIT: unless the function is supposed to have different definitions in different compilation units, perhaps due to different preprocessor macros that are defined before including the header file. In that case the best approach is not to include it at all, but rather to bury it in an unmarked grave with a stake through its unholy heart.)Data objects, apart from constants, usually shouldn't be defined in header files at all, only declared
extern
.Static member functions are a different kettle of fish, and you have to use
static
there as there is no other way to declare them. That usage isn't deprecated, since it isn't in namespace scope.UPDATE: C++11 has removed the deprecation, so there's no longer any particular reason to prefer unnamed namespaces over
static
. But you still shouldn't use either in a header file unless you're doing something weird.据我所知,命名空间范围内的静态与未命名的命名空间相比没有任何优势。使用未命名的命名空间,如上例所示。实际上,在上面的示例中,我不明白为什么需要静态或未命名的命名空间。也许内联?
静态成员函数与命名空间范围内的静态无关。静态成员函数(和非函数成员)仍然有效。
There is no advantage of static in namespace scope over unnamed namespaces which I know of. Use unnamed namespaces, as in the example above. Actually in the example above I can't see why is static or unnamed namespace necessary. Maybe inline?
And static member functions have nothing to do with static at namespace scope. Static member functions (and nonfunction members) are still valid.
在头文件中,通常没有必要指定内部链接或使用匿名名称空间。
在单独编译的实现文件中,您可以使用
static
或匿名命名空间来避免链接级别名称冲突或客户端代码依赖于实现细节。匿名命名空间允许您拥有外部链接,这是模板参数所必需的,并且它还支持类定义。但最终这只是一个实用性和个人喜好的问题,具体情况而定。成员函数的
static
与链接规范无关。无论如何,静态成员函数都具有外部链接。In a header file there's usually no point in specifying internal linkage, or using an anonymous namespace.
In a separately compiled implementation file you can use
static
or an anonymous namespace to avoid linkage level name collisions or client code relying on implementation details. An anonymous namespace lets you have external linkage, which is required for template parameters, and it also supports class definitions. But in the end it's just a question of practicality and personal preference, on a case by case basis.static
for a member function has nothing to do with linkage specification. Astatic
member function has external linkage anyway.如果您使用某些工具,
static
可能会更好。在大多数文本编辑器中,它的自动缩进功能也表现得更好一些。当你不得不避免使用一些有用的东西时,这有点悲伤,因为它不能与真正支持它的工具一起使用,但我保证你会克服它。一个示例问题暗示了调试部门的潜在痛苦:
查看Visual Studio 调试器中的命名空间全局变量?
您可能不必费力寻找更多问题,但调试器问题足以让我在最大程度上完全放弃命名空间,所以我从来没有进一步看过。
我个人的建议是,对于不会永远存在的代码,最好使用
static
。实际上与未命名命名空间执行相同的操作,但是,在所有工具中平均而言,它得到了更好的支持。从理论上讲,有一天它会完全消失,但我很高兴公开承认,我确信那一天永远不会真正到来。同时,你也可以为自己省去一些痛苦。static
can be preferable if you are using some tools. It also behaves a bit better with auto indent functionality in most text editors. It's a bit sad, when you have to avoid using something useful because it doesn't work with tools that should really support it, but I promise you'll get over it.An example question that gives some hint of potential pain in the debugging department:
Viewing namespaced global variables in Visual Studio debugger?
You probably won't have to look very hard to find more problems, but the debugger issues were enough to make me entirely give up on namespaces, to the maximum extent possible, so I've never looked any further.
My personal recommendation is that for code that will be around for less than forever, one might as well go with
static
. Does effectively the same thing as an unnamed namespace, but, averaged out over all tools, it is better supported. In theory, one day it will disappear completely, but I'm happy to publicly admit that I'm certain that day will never actually come to pass. And in the mean time, you are saving yourself some pain.