在 C++ 中,使用某种前缀来命名成员变量是很常见的,以表示它们是成员变量,而不是局部变量或参数。如果您来自 MFC 背景,您可能会使用m_foo. 我也myFoo偶尔看到。
m_foo
myFoo
C#(或者可能只是 .NET)似乎建议只使用下划线,如_foo. 这是 C++ 标准允许的吗?
_foo
规则(在 C++11 中没有改变):
std
来自 2003 C++ 标准:
17.4.3.1.2 全局名称 [lib.global.names] 某些名称和函数签名集始终保留给实现: 每个包含双下划线 ( __) 或以下划线后跟大写字母 (2.11) 的名称都保留给实现以供任何使用。 每个以下划线开头的名称都保留给实现用作全局名称空间中的名称。165 165)此类名称也保留在命名空间::std(17.4.3.1) 中。
某些名称和函数签名集始终保留给实现:
__
165)此类名称也保留在命名空间::std(17.4.3.1) 中。
::std
因为 C 基于 C 标准(1.1/2,C03),而 C99 是规范性参考(1.2/1,C++03),这些也适用于 1999 年的 C 标准:
7.1.3 保留标识符 每个标头声明或定义其相关子条款中列出的所有标识符,并可选地声明或定义其相关的未来库方向子条款中列出的标识符和始终保留用于任何用途或用作文件范围标识符的标识符。 以下划线和大写字母或另一个下划线开头的所有标识符始终保留用于任何用途。 所有以下划线开头的标识符始终保留用作普通和标记名称空间中具有文件范围的标识符。 如果包含任何关联的头文件,则以下任何子条款(包括未来的库方向)中的每个宏名称都保留用于指定用途;除非另有明确说明(见 7.1.4)。 以下任何子条款(包括未来的库方向)中具有外部链接的所有标识符始终保留用作具有外部链接的标识符。154 * 如果包含任何关联的标头,则保留在以下任何子条款(包括未来的库方向)中列出的具有文件范围的每个标识符用作宏名称和具有相同名称空间中的文件范围的标识符。 没有保留其他标识符。如果程序在保留标识符的上下文中声明或定义标识符(7.1.4 允许的除外),或将保留标识符定义为宏名称,则行为未定义。 如果程序删除(用#undef)上面列出的第一组中标识符的任何宏定义,则行为未定义。 154)具有外部链接的保留标识符列表包括errno、math_errhandling、setjmp和va_end。
每个标头声明或定义其相关子条款中列出的所有标识符,并可选地声明或定义其相关的未来库方向子条款中列出的标识符和始终保留用于任何用途或用作文件范围标识符的标识符。
没有保留其他标识符。如果程序在保留标识符的上下文中声明或定义标识符(7.1.4 允许的除外),或将保留标识符定义为宏名称,则行为未定义。
如果程序删除(用#undef)上面列出的第一组中标识符的任何宏定义,则行为未定义。
#undef
154)具有外部链接的保留标识符列表包括errno、math_errhandling、setjmp和va_end。
errno
math_errhandling
setjmp
va_end
其他限制可能适用。例如,POSIX 标准保留了很多可能出现在正常代码中的标识符:
E
is
to
LC_
f
l
SIG
SIG_
str
mem
wcs
PRI
SCN
X
_t
虽然现在将这些名称用于您自己的目的可能不会导致问题,但它们确实会增加与该标准的未来版本冲突的可能性。
就我个人而言,我只是不使用下划线开头的标识符。我的规则的新增内容:不要在任何地方使用双下划线,这很容易,因为我很少使用下划线。
在对这篇文章进行研究之后,我不再以标识符结尾,_t 因为这是 POSIX 标准保留的。
关于任何以结尾的标识符的规则_t让我很惊讶。我认为这是一个 POSIX 标准(尚不确定),需要澄清和官方章节。这来自GNU libtool 手册,列出了保留名称。
CesarB 提供了以下指向POSIX 2004保留符号的链接,并指出“可以在此处找到许多其他保留的前缀和后缀……”。POSIX 2008保留符号在此处定义。 这些限制比上述限制更细微。