箭头-> 运算符重载如何在 C++ 内部工作?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10677804/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:19:56  来源:igfitidea点击:

How arrow-> operator overloading works internally in c++?

c++operator-overloading

提问by Ryan

I understand the normal operator overloading. Compiler can translate them to method call directly. I am not very clear about the -> operator. I was writing my first custom iterator and I felt like the need of -> operator. I took a look at the stl source code and implemented my own like it:

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

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

Then I can use an instance of MyClassIterator like:

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

myClassIterator->APublicMethodInMyClass().

Looks like the compiler does two steps here. 1. Call the ->() method the get a temporary MyClass* variable. 2. Call the APublicMethodInMyClass on the temp variable use its -> operator.

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

Is my understanding correct?

我的理解正确吗?

采纳答案by dirkgently

myClassIterator->APublicMethodInMyClass()

is nothing but the following:

无非是以下内容:

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

The first call to the overloaded operator->gets you a pointer of some type which has an accessible (from your call-site) member function called APublicMethodInMyClass(). The usual function look-up rules are followed to resolve APublicMethodInMyClass(), of course, depending on whether it is a virtual or not.

对重载的第一次调用operator->会为您提供某种类型的指针,该指针具有一个可访问的(从您的调用站点)成员函数,称为APublicMethodInMyClass(). 遵循通常的函数查找规则来解析APublicMethodInMyClass(),当然取决于它是否是虚拟的。

There is not necessarily a temporary variable; the compiler may or may not copy the pointerreturned by &(m_iterator->second). In all probability, this will be optimized away. No temporary objects of type MyClasswill be created though.

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

The usual caveats also do apply to m_iterator-- make sure that your calls do not access an invalidated iterator (i.e. if you are using vectorfor example).

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

回答by David Rodríguez - dribeas

The operator->has special semantics in the language in that, when overloaded, it reapplies itself to the result. While the rest of the operators are applied only once, operator->will be applied by the compiler as many times as needed to get to a raw pointer and once more to access the memory referred by that pointer.

operator->具有在该语言,超载时,重新应用本身的结果特殊的语义。虽然其余的运算符仅应用一次,operator->但编译器将根据需要多次应用以获取原始指针并再次访问该指针所引用的内存。

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

In the previous example, in the expression d->foo()the compiler will take the object dand apply operator->to it, which yields an object of type C, it will then reapply the operator to get an instance of B, reapply and get to A*, after which it will dereference the object and get to the pointed data.

在前面的例子中,在表达式中d->foo(),编译器将获取对象d并应用operator->到它,这会产生一个类型的对象,C然后它会重新应用运算符来获取B、重新应用和获取到的实例,A*然后它将取消引用该对象并获得指向的数据。

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