Soc*_*cob 2 c++ syntax member-access scope-resolution-operator
在cppreference.com \xe2\x80\x93 \xe2\x80\x9cQualified name Lookup\xe2\x80\x9d上,我发现了这个奇怪的代码示例:
\nstruct C { typedef int I; };\n\ntypedef int I1, I2;\n\nextern int *p, *q;\n\n// Slight modification to prevent linker error\n//struct A { ~A(); };\nstruct A { ~A() {}; };\n\ntypedef A AB;\n\nint main()\n{\n p->C::I::~I(); // The name I after ~ is looked up in the same scope as I before ::\n // (that is, within the scope of C, so it finds C::I)\n\n q->I1::~I2(); // The name I2 is looked up in the same scope as I1\n // (that is, from the current scope, so it finds ::I2)\n\n AB x;\n x.AB::~AB(); // The name AB after ~ is looked up in the same scope as AB before ::\n // (that is, from the current scope, so it finds ::AB)\n}\nRun Code Online (Sandbox Code Playgroud)\n令我惊讶的是,编译没有任何错误。但到底发生了什么
\np->C::I::~I();\nq->I1::~I2();\nRun Code Online (Sandbox Code Playgroud)\n?这不仅看起来像 it\xe2\x80\x99 访问int变量的成员并以某种方式引用int析构函数,而且p和q也是extern没有任何定义的变量。
为什么这种语法是被允许的,它实际上做了什么?
\n\n\n并以某种方式引用 int 析构函数,
\n
这些是伪析构函数调用。不使用类型别名的限定查找的直接表示法是
\np->~int();\nq->~int();\nRun Code Online (Sandbox Code Playgroud)\n如果是标量类型而不是类类型,则符号x.~T()orp->~T()始终是伪析构函数调用。T在这种情况下x必须有 typeT和ptype int*。
伪析构函数调用结束对象x/的生命周期*p,就像普通的析构函数调用一样,但不执行任何其他操作。特别是它不调用任何析构函数(标量类型没有)。它的存在只是为了让人们可以编写适用于类和非类类型的通用代码,而无需调用特殊情况的析构函数。
\n\n这不仅看起来像是\xe2\x80\x99s访问int变量的成员
\n
这在评论和链接的 cppreference 文章本身中进行了解释。后跟限定名称的符号并不意味着要查找p->类型的成员。*p相反,根据本文中提供的规则,查找还可以考虑当前范围。但是,如果*p不是类类型,则伪析构函数调用是此类查找的唯一结果,不会导致表达式最终格式错误。
\n\n但 p 和 q 也是没有任何定义的外部变量。
\n
伪析构函数调用 odr-usep和q,因此程序中必须存在它们的定义。但是,它可能位于不同的翻译单元中。即使它不存在,这样的 odr 违规也会使程序 IFNDR(格式错误,无需诊断),因此编译器不必抱怨它。毕竟,这些行实际上不会导致发出任何机器代码,因此没有理由麻烦链接器来查找p和 的定义q的定义。