为什么编译器会调用 - >操作员两次

时间:2012-09-11 08:11:38

标签: c++

以下代码摘自:https://github.com/facebook/folly/blob/master/folly/Synchronized.h

我最近看了一下Folly库,发现了一些有趣的东西。请考虑以下示例:

#include <iostream>

struct Lock {
    void lock() {
        std::cout << "Locking" << std::endl;
    }
    void unlock() {
        std::cout << "Unlocking" << std::endl;
    }
};

template <class T, class Mutex = Lock >
struct Synchronized {
    struct LockedPtr {
        explicit LockedPtr(Synchronized* parent) : p(parent) {
            p->m.lock();
        }

        ~LockedPtr() {
            p->m.unlock();
        }

        T* operator->() {
            std::cout << "second" << std::endl;
            return &p->t;
        }

    private:
        Synchronized* p;
    };

    LockedPtr operator->() {
        std::cout << "first" << std::endl;
        return LockedPtr(this);
    }

private:
    T t;
    mutable Mutex m;
};

struct Foo {
    void a() {
        std::cout << "a" << std::endl;
    }
};

int main(int argc, const char *argv[])
{
    Synchronized<Foo> foo;
    foo->a();

    return 0;
}

输出结果为:

first
Locking
second
a
Unlocking

我的问题是:为什么这段代码有效?这种模式有名字吗?

- &gt;运算符被调用两次,但它只写了一次。

2 个答案:

答案 0 :(得分:12)

因为那是标准所说的:

13.5.6班级成员访问[over.ref]

  

1)operator->应为非静态成员函数,否则为   参数。它使用-> postfix-expression -> id-expression实现类成员访问解释表达式x->m   对于类型为(x.operator->())->m的类对象x,为T if   如果运营商被选为最佳运营商,则存在T::operator->()   通过重载解析机制匹配函数(13.3)。

(强调我的)

在您的情况下,xfooma(),现在,Synchronized重载operator->foo->a()相当于:

(foo.operator->())->a();

foo.operator->()是您在课程Synchronized中的重载,它会返回LockedPtr,然后LockedPtr会调用自己的operator->

答案 1 :(得分:0)

问问自己:它怎么可能表现出来?

请记住,重载operator->的重点是智能指针类可以使用与原始指针相同的语法。也就是说,如果你有:

struct S
{
    T m;
};

并且指针p指向S,然后您通过S::m访问p->m,无论pS*还是一些pointer_class<S>类型。

使用->和直接调用operator->之间也存在差异:

pointer_class<S> pointerObj;
S* p = pointerObj.operator->();

请注意,如果使用重载->并未自动降低额外级别,那么p->m可能意味着什么?如何使用过载?