【问题标题】:How arrow-> operator overloading works internally in c++?箭头-> 运算符重载如何在 C++ 内部工作?
【发布时间】:2012-05-27 12:20:08
【问题描述】:

我了解正常的运算符重载。编译器可以直接将它们转换为方法调用。我对 -> 运算符不是很清楚。我正在编写我的第一个自定义迭代器,我觉得需要 -> 运算符。我看了一下stl源代码并实现了自己的喜欢它:

MyClass* MyClassIterator::operator->() const
{
    //m_iterator is a map<int, MyClass>::iterator in my code.
    return &(m_iterator->second);
}

然后我可以使用 MyClassIterator 的实例,例如:

myClassIterator->APublicMethodInMyClass().

看起来编译器在这里做了两个步骤。 1. 调用 ->() 方法获取一个临时的 MyClass* 变量。 2. 在临时变量上调用 APublicMethodInMyClass 使用它的 -> 操作符。

我的理解正确吗?

【问题讨论】:

    标签: c++ operator-overloading


    【解决方案1】:
    myClassIterator->APublicMethodInMyClass()
    

    只不过是以下内容:

    myClassIterator.operator->()->APublicMethodInMyClass()
    

    对重载的operator-&gt; 的第一次调用会为您获取某种类型的指针,该指针具有称为APublicMethodInMyClass() 的可访问(来自您的调用站点)成员函数。解析APublicMethodInMyClass()遵循通常的函数查找规则,当然要看是不是虚函数了。

    不一定有临时变量;编译器可能会也可能不会复制&amp;(m_iterator-&gt;second) 返回的指针。很可能,这将被优化掉。但不会创建 MyClass 类型的临时对象。

    通常的警告也适用于m_iterator——确保您的调用不会访问无效的迭代器(例如,如果您使用的是vector)。

    【讨论】:

    • 其实是myClassIterator.operator-&gt;()-&gt;APublicMethodInMyClass()
    • 感谢您的解释。 myClassIterator.operator->().APublicMethodInMyClass() 应该是 myClassIterator.operator->()->APublicMethodInMyClass() 吗? ->() 的返回类型是 MyClass*
    • @SethCarnegie:是的!修正错字。
    • 另见google.com/search?q=c%2B%2B+drill-down%20operator。箭头运算符在 C++ 中是独一无二的。
    • @Potatoswatter 我们应该阅读哪个链接?指向 Google 搜索的链接并没有那么有用。
    【解决方案2】:

    operator-&gt; 在语言中具有特殊的语义,当重载时,它会将自身重新应用于结果。虽然其余的运算符只应用一次,但operator-&gt; 将由编译器根据需要应用多次以获取原始指针并再次访问该指针所引用的内存。

    struct A { void foo(); };
    struct B { A* operator->(); };
    struct C { B operator->(); };
    struct D { C operator->(); };
    int main() {
       D d;
       d->foo();
    }
    

    在前面的示例中,在表达式 d-&gt;foo() 中,编译器将获取对象 d 并将 operator-&gt; 应用于它,这会产生一个类型为 C 的对象,然后它将重新应用该运算符以获得一个B的实例,重新申请并到达A*,之后它将取消引用该对象并获得指向的数据。

    d->foo();
    // expands to:
    // (*d.operator->().operator->().operator->()).foo();
    //   D            C            B           A*
    

    【讨论】:

    • 你能给我指个参考吗?似乎找不到任何东西。甚至没有其他人提到它。
    • @MilindR: 13.5.6/1[...] 如果 T::operator-&gt;() 存在且类型为 T 的类对象 x,则表达式 x->m 被解释为 (x.operator-&gt;())-&gt;m如果运算符被重载解析机制选择为最佳匹配函数 如果x-&gt;operator-&gt;() 产生一个指针,它会被取消引用,如果它产生一个重载operator-&gt;() 类型的对象,则调用该运算符。
    • @MilindR:接受的答案确实是这样说的,尽管它的含义并不那么明确:myClassIterator.operator-&gt;()-&gt;APublicMethodInMyClass()(第二段代码)
    • @DavidRodríguez-dribeas:是的,您可以从已接受答案代码的第二行推断出一些递归,但在您的答案中更好地解释(事实上,递归对我来说是不可见的,直到我读你的)。谢谢!
    • 一直以来我都认为我必须手动编写递归来获取指针。 +1 奇怪的花絮。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-20
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    相关资源
    最近更新 更多