箭头运算符->与作用域解析运算符::组合的含义及语法解析
限定名查找特殊语法的疑问解答
先看cppreference上的示例代码:
struct C { typedef int I; }; typedef int I1, I2; extern int *p, *q; // Slight modification to prevent linker error //struct A { ~A(); }; struct A { ~A() {}; }; typedef A AB; int main() { p->C::I::~I(); // The name I after ~ is looked up in the same scope as I before :: // (that is, within the scope of C, so it finds C::I) q->I1::~I2(); // The name I2 is looked up in the same scope as I1 // (that is, from the current scope, so it finds ::I2) AB x; x.AB::~AB(); // The name AB after ~ is looked up in the same scope as AB before :: // (that is, from the current scope, so it finds ::AB) }
为什么这种语法被允许?
- 首先,
p->C::I::~I()不是真的要调用int的析构函数。int是标量类型,本身没有用户定义的析构函数,但C++语法允许这种写法——它本质是用来演示限定名查找规则:~后面的名字的查找范围,和::前面的名字的查找范围完全一致。这里C::I里的I是在struct C的作用域里,所以~后面的I也会在C的作用域查找,最终匹配到C::I这个typedef。编译器不会为标量类型生成实际的析构调用代码,因为标量的析构是trivial(无操作)的,所以这段代码能通过编译。 - 关于
extern int *p, *q:extern只是告诉编译器“这些变量在其他地方定义”,如果代码中没有实际用到p、q的内存地址(比如trivial析构的调用会被优化掉,不需要解引用指针),那么链接时不会报错——这段代码的核心是验证语法规则,不是要实际执行指针操作。
实际作用是什么?
- 这种写法的核心价值在泛型/模板编程里:当你不确定模板参数
T是类类型还是标量类型时,统一用obj->T::~T()的写法可以兼容两种情况。如果T是类类型,会正确调用其析构函数;如果是标量类型,编译器会忽略这个无意义的调用(因为trivial析构不会生成代码),避免了分支判断的麻烦。 - 这段示例代码的直接目的,就是直观展示限定名查找的特殊规则:
~后的名字查找范围和::前的名字的查找范围绑定,比如q->I1::~I2()里的I1是全局作用域的typedef,所以~后的I2也会在全局作用域查找;而x.AB::~AB()里的AB是当前作用域的typedef,所以~后的AB同样在当前作用域查找。
内容的提问来源于stack exchange,提问作者Socob
相关产品推荐
相关产品推荐

