C ++成员访问/间接运算符等价

时间:2016-03-02 19:33:12

标签: c++ pointers language-lawyer

我正在查看有关成员引用运算符的C ++标准(一元*解引用运算符,->成员访问运算符)以及许多其他相关问题:

C++ - Difference between (*). and ->?

ptr->hello(); /* VERSUS */ (*ptr).hello();

C++ pointers difference between * and ->

我看到大多数答案都说p->m是C ++标准(5.2.5,第2段)定义的(*p).m的语法糖:

  

表达式E1->E2将转换为等效形式(*(E1)).E2

许多评论还指出,因为operator*operator->在类中是可重载的,所以它们应该统一重载以确保一致的行为。

这些陈述似乎相互矛盾:如果(根据标准)E1->E2转换为等效形式(*(E1)).E2,那么重载operator->的目的是什么(如是否允许标准)?

更简单的说明,标准的这两部分是否存在冲突,还是我误解了标准? 对E1->E2的{​​{1}}等价转换是否适用于所有完整类型或仅适用于内置类型?

1 个答案:

答案 0 :(得分:5)

E1 -> E2(*(E1)).E2的转换仅适用于原始指针类型。对于类类型,E1 -> E2求值为(E1).operator->().E2,如果operator->的返回类型本身不是指针类型,则operator->可能会递归扩展更多operator*的副本。您可以通过创建支持operator->但不支持operator->的类型并尝试在其上使用箭头运算符来查看此内容;您将收到operator ->未定义的错误。

作为后续工作,以operator *方式实现->的方式很常见,其方式使得PointerType ClassType::operator-> () const { return &**this; } 的语义与指针的语义相匹配。你经常会看到这样的事情:

&(*(*this)),

此表达式被解释为

*this

含义"获取此对象(*(*this)),取消引用它(&(*(*this))),并获取您找到的地址(E1 -> E2。)。"现在,如果您使用(*(E1)).E2应该等同于{{1}}的规则,您可以看到最终得到的内容相同。