[英]Why does the compiler invoke the -> operator twice
The following code is extracted from: https://github.com/facebook/folly/blob/master/folly/Synchronized.h 以下代码摘自: https : //github.com/facebook/folly/blob/master/folly/Synchronized.h
I recent had a look at the Folly library, and found something interesting. 我最近看了一下Folly库,发现了一些有趣的东西。 Consider the following example:
请考虑以下示例:
#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;
}
The output is: 输出是:
first
Locking
second
a
Unlocking
My question is: Why is this code valid? 我的问题是:为什么这段代码有效? Does this pattern have a name?
这个模式有名字吗?
The -> operator is called twice, but it has only been written once. - >运算符被调用两次,但它只写了一次。
Because that's what the standard says: 因为这就是标准所说的:
1)
operator->
shall be a non-static member function taking no parameters.1)
operator->
应该是一个不带参数的非静态成员函数。 It implements class member access using-> postfix-expression -> id-expression
An expressionx->m
is interpreted as(x.operator->())->m
for a class objectx
of typeT
ifT::operator->()
exists and if the operator is selected as the best match function by the overload resolution mechanism (13.3).它使用
-> postfix-expression -> id-expression
实现类成员访问如果T::operator->()
表达式x->m
被解释为(x.operator->())->m
表示类型为T
的类对象x
T::operator->()
存在,如果操作符被重载决策机制选为最佳匹配函数(13.3)。
(emphasis mine) (强调我的)
In your case, x
is foo
and m
is a()
, Now, Synchronized
overloads operator->
, foo->a()
is equivalent to: 在你的情况下,
x
是foo
, m
是a()
,现在, Synchronized
重载operator->
, foo->a()
相当于:
(foo.operator->())->a();
foo.operator->()
is your overload in class Synchronized
, which returns a LockedPtr
, and then that LockedPtr
calls its own operator->
. foo.operator->()
是您在Synchronized
类中的重载,它返回一个LockedPtr
,然后LockedPtr
调用它自己的operator->
。
Ask yourself this: how else could it possibly behave? 问问自己:它可能还有什么其他表现?
Remember, the point of overloading operator->
at all is so that a smart pointer class can use the same syntax as a raw pointer. 请记住,重载
operator->
的重点是智能指针类可以使用与原始指针相同的语法。 That is, if you have: 也就是说,如果你有:
struct S
{
T m;
};
and you have a pointer p
to S
, then you access S::m
via p->m
regardless of whether p
is an S*
or some pointer_class<S>
type. 并且你有一个指针
p
到S
,然后通过p->m
访问S::m
,无论p
是S*
还是某个pointer_class<S>
类型。
There's also the difference between using ->
and invoking operator->
directly: 使用
->
和直接调用operator->
之间也有区别:
pointer_class<S> pointerObj;
S* p = pointerObj.operator->();
Note that if using an overloaded ->
didn't automatically descend the extra level, what would p->m
ever possibly mean? 请注意,如果使用重载
->
没有自动降低额外级别,那么p->m
可能意味着什么? How could the overload ever be used? 如何使用过载?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.