为什么要添加名字std
命名空间未定义的行为?
显而易见的答案是“因为标准是这么说的”,例如在 C++14 [命名空间.std] 17.6.4.2.1/1 中:
如果 C++ 程序向命名空间添加声明或定义,则其行为是未定义的std
或到一个
命名空间内的命名空间std
除非另有规定。 ...
然而,我真的很想知道这个裁决的原因。我当然可以理解添加已经存在的名称的重载std
可能会破坏行为;但为什么添加新的、不相关的名称会成为问题呢?
程序已经可以在内部造成严重破坏std
使用宏,这就是为什么几乎所有标准库实现都必须仅包含所有非公共部分的保留名称(双下划线和下划线开头的大写字母)。
我真的对这样的情况可能会出现问题很感兴趣:
namespace std
{
int foo(int i)
{ return i * 42; }
}
#include <algorithm> // or one or more other standard library headers
当这是完全合法的并且标准库必须应对时:
#define foo %%
#include <algorithm> // or one or more other standard library headers
这种未定义行为的理由是什么?
以下是几个原因:
- 即使名字在headers必须进行丑化以避免与宏交互,但实际实现代码的源文件中的名称不存在此要求。如果一个实现确实使用了
::std::foo(int)
作为其实施的一部分,这将违反单一定义规则。
- 该标准预计会不断增长。名称是否可以添加到命名空间
std
添加到标准 C++ 库中的任何名称都可能是重大更改。在某种程度上,这已经是正确的,因为任何这样的名称都可以是宏,但破坏这些名称被认为是可以接受的。
- 实际上不需要将名称添加到命名空间
std
:它们可以添加到任意其他名称空间,即,即使上面给出的动机不是特别强烈,任何形式的限制都不被认为是重要的。 ...如果有的话is将名称添加到命名空间的原因std
, 很明显does影响行为。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)