为什么允许我们获取不完整类型的地址?
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
并接受它。
考虑这段代码:
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 declaresoperator&()
, 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
并接受它。