我正在浏览Google C++ style guide,发现了这个:
“不要在命名空间 std 中声明任何东西,甚至不要前向声明标准库类。在命名空间 std 中声明实体是未定义的行为,即不可移植。要从标准库声明实体,请包含适当的头文件。”
有人可以使用示例代码解释这意味着什么以及为什么这是未定义的行为吗?
我正在浏览Google C++ style guide,发现了这个:
“不要在命名空间 std 中声明任何东西,甚至不要前向声明标准库类。在命名空间 std 中声明实体是未定义的行为,即不可移植。要从标准库声明实体,请包含适当的头文件。”
有人可以使用示例代码解释这意味着什么以及为什么这是未定义的行为吗?
有人可以使用示例代码解释这意味着什么以及为什么这是未定义的行为吗?
以下程序产生未定义的行为:
namespace std {
void foo(int) { }
}
#include <iostream>
int main() {
std::cout << "Hello World!" << std::endl;
}
为什么?它声明了一个名为foo
namespace的函数std
。至于为什么这会导致问题,请考虑:标准库实现可能有自己的函数命名foo()
,并且可能被<iostream>
. 你foo
可能会比标准库实现的foo
.
首先,就像许多谷歌风格指南一样,它实际上是错误的。该标准特别允许您在命名空间 std 中定义一些特定实体(例如,现有模板在用户定义类型上的特化)。
然而,忽略这些异常,它们确实有正确的总体思路——您的代码通常属于命名空间 std 以外的某个地方。您可以将它放在全局命名空间中,也可以定义另一个命名空间,但您应该不理会它std
。
您也不应该尝试在标准库中前向声明任何内容。允许(例如)标准函数包含额外参数,只要它们包含默认值,因此可以以标准方式调用它们。如果您尝试自己声明它们,而不是声明现有函数,您最终可能会声明一个模棱两可的重载。
底线:是的,使用标准库。当您使用它时,请通过包含标准标头而不是尝试编写自己的标头来获取声明。
这就是说不要在std
命名空间中声明自己的类型。您可以使用标准库,但您应该通过包含适当的标头来做到这一点。
基本上,确保您的所有声明都在您自己的命名空间中,而不是std
.
他们说你不应该像这样从标准库中转发声明东西:
// myheader.h
namespace std{
template<class T>
void SomeStandardFunction();
}
// use std::SomeStandardFunction
相反,您应该直接包含标题:
// myheader.h
#include <SomeHeaderThatContainsSomeStandardFunction>
// use std::SomeStandardFunction
这并不是说“不要使用标准库”。
使用某物和声明某物是两件不同的事情。它的意思是不要声明任何东西,因为不要做类似“class ostream;”的事情。我想人们过去必须像这样声明它才能使用它,但现在,由于东西是在命名空间 std 中声明的,你只需包含头文件。
看看这个。