类中成员声明的重新排序规则
Posted
技术标签:
【中文标题】类中成员声明的重新排序规则【英文标题】:Rule of reordering member declaration in class 【发布时间】:2014-05-21 03:35:49 【问题描述】:我正在阅读 c++14 N3797,我遇到过 3.3.7/1:
如果对类中的成员声明重新排序会产生一个替代的有效 (1) 和 (2) 下的程序,程序格式错误,没有诊断 必填。
有(1)和(2):
1) 类中声明的名称的潜在范围不仅包括 在名称的声明点之后的声明区域, 还有所有函数体,默认参数, 异常规范和大括号或等式初始化器 该类中的非静态数据成员(包括嵌套中的此类内容 类)。
2) 在类 S 中使用的名称 N 应引用相同的声明 它的上下文以及在 S 的完整范围内重新评估时。否 违反此规则需要进行诊断。
如果我们这样写:
class A
int a;
int b;
那么程序格式错误。重新定义成员声明会产生一个替代的有效程序:
class A
int b;
int a;
我可能没有正确理解这条规则吗?
【问题讨论】:
这肯定不会创建一个替代有效程序。它可能看起来不同,但它会编译和执行相同的。 【参考方案1】:“替代有效程序”是指类中元素的每个排序都会产生对程序的有效解释,但含义会根据排序而变化。 p>
在您的情况下,允许更改 a
和 b
的顺序,但是由于它们的相对顺序不会影响程序的含义,因此定义了行为。 p>
为此,您必须在类中使用一个名称,该名称已在该类之外具有其他含义。例如:
typedef void *T;
struct whatever
T a;
typedef long T;
;
这里a
的声明和T
的typedef的相对顺序影响了代码的含义。正如现在所写的那样,a
的类型为 void *
,因为当解析 T a;
时,全局 typedef void *T;
在范围内。
但是,如果我们将两者重新排列为:
typedef void *T;
struct whatever
typedef long T;
T a;
;
...T a;
等价于long a;
。由于两个声明的相对顺序,程序的含义不同,所以行为是未定义的。
【讨论】:
你能举一个例子说明它的顺序何时会影响程序的含义吗? 看来我开始明白了。在这种情况下,重新排序之前和之后的行为可能会有所不同。我理解正确吗? 是的。我添加了一个示例。 像if (&whatever::a < &whatever::b)
这样的代码会被认为受到影响,还是会被修复并给出预期的结果?
@chris:我想您可以将其解释为属于上述引用,但我不认为它打算被涵盖。真正的意图是像我上面展示的那样,当您更改声明的顺序时,程序的基本含义(例如T
所指的类型)会发生变化。如果您在更改顺序时包含(可能)更改的成员地址,那么基本上每个具有多个非静态数据成员的结构/类都有 UB,我很确定这不是故意的。以上是关于类中成员声明的重新排序规则的主要内容,如果未能解决你的问题,请参考以下文章