Wu Yongwei
Wu Yongwei
> 原本 CWG 315 的描述并不是我说的语义。当时同样要求指针解引用,只是没有说解引用空指针是 UB。 > 我说的是把这种情况改成根本不进行解引用。理由是没必要进行冗余的操作。 我的理解是一回事。原先的语义:不实际会发生的空指针解引用不是未定义行为。现在的语义:只要形式上写出了对空指针解引用,就是未定义行为。你的说法跟原先的语义靠拢。 原先的语义一样有灰色地带:如果一个非静态成员函数不直接或间接访问当前对象的任何数据成员,那我们可以在空指针上调用这个函数吗?实际编译器不会产生有问题的代码,但标准仍认为这是未定义行为,有些工具也能进行告警。 如果要说服标准委员会改变态度,得有一个有说服力的用例,让别人看到有让这个行为定义的必要吧。我没看到。
> 理由是没必要进行冗余的操作。 你说的这个“冗余”操作从来就没发生过。这也是之前 CWG315 认为这不是未定义行为的原因。 现在标准我觉得是想把这个问题简化、统一处理。就是没必要对静态成员函数的调用特殊处理。如果只拿实际行为来辩,规则里给出的 `p->bar()` 也可以是合法的了。
> 解引用一直都是实际发生的。 从编译器产生代码的角度,解引用从来没发生过。从形式的角度,解引用一直存在。CWG 315 原先的合法化方式也是说 `*p` 没有做 lvalue-to-rvalue 转换就行(实际上也是有点别扭的)。 最关键点我已经说了,只有有人觉得写 `p->baz()` 需要在 `p` 为空时合法,认定这很重要,一定要保证它有定义行为,才会有动力去写个提案吧。我看不出目前讨论的人里谁有。
我似乎明白你的意思了。你是说 constexpr 求值里应当没有任何未定义行为这个问题吧?……
> 此时 GCC 与 Clang 是正确拒绝的([Godbolt link](https://godbolt.org/z/c6Wq9PM3j))。 > (MSVC 目前没有正确拒绝。) 你的这个例子在 GCC 13 和最新的 MSVC 下都没有报错。GCC 14 能进行处理,说明在对空指针解引用的解释方面已经有了改变。可以想象,以后通过空指针调用静态成员函数也同样会报错。 还是我前面说的,需要有人觉得写 `p->baz()` 应该在 `p` 为空时合法,认定这很重要,一定要保证它有定义行为。你也没这么认为吧。这毕竟是边角情况,没人会正常这么写。让编译器对其报错,对编译器厂商可能是个小小的负担,但看 GCC 从 13 到 14 变化,应该也不算太麻烦。