类中成员声明的重新排序规则

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>

在您的情况下,允许更改 ab 的顺序,但是由于它们的相对顺序不会影响程序的含义,因此定义了行为。 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,我很确定这不是故意的。

以上是关于类中成员声明的重新排序规则的主要内容,如果未能解决你的问题,请参考以下文章

Maven POM 文件:关于元素和部分排序的任何规则?

Mysql中的UTF-8字符集与字符集排序规则的选择

初级排序算法1-定义排序规则

firebird 设置不区分大小写的排序规则

内置容器的排序规则构造方式

微信通讯录分组/好友排序有啥规则?