为什么允许我们获取不完整类型的地址?

Why are we allowed to take the address of an incomplete type?

考虑这段代码:

class Addressable;
class Class1  { void foo(Addressable &a) { (void) &a; } };  // OK
class Addressable { void *operator &() { return this; } };
class Class2  { void foo(Addressable &a) { (void) &a; } };  // Error: operator & private

为什么 C++ 允许获取不完整引用类型的地址?

如上所示,它不会有潜在的违法性吗?这是故意的吗?

是的,这是故意的,如果 operator& 过载,可能会损坏。

获取不完整类型的地址早在 C++ 之前就已成为可能。在 C 中,绝对没有任何损坏的风险,因为 & 不能重载。

C++ 选择不不必要地破坏以前有效的程序,并简单地指定如果不完整的类型确实具有重载的 & 运算符,则未指定是否使用重载运算符。

引用 N4140:

5.3.1 Unary operators [expr.unary.op]

If & is applied to an lvalue of incomplete class type and the complete type declares operator&(), it is unspecified whether the operator has the built-in meaning or the operator function is called.

这可以解释为甚至适用于当前正在声明的 class,甚至当已经看到 operator& 的声明时:

extern struct A a;
struct A {
  int operator&();
  decltype(&a) m; // int, or A *?
};
int main() {
  return A().m; // only valid if m is int
}

在这里,GCC 给出 m 类型 A * 并拒绝该程序,但是 clang 给出它类型 int 并接受它。