为什么编译器调用 -> 运算符两次
Why does the compiler invoke the -> operator twice
代码提取自: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
我的问题是:为什么这个代码有效?此模式有名称吗?
-> 运算符被调用两次,但只被写入过一次。
因为这就是标准所说的:
13.5.6 类成员访问 [over.ref]
1(
operator->
应为非静态成员函数,不采取 参数。它使用-> postfix-expression -> id-expression
解释表达式x->m
实现类成员访问 作为类对象的(x.operator->())->m
,x
类型为T
如果T::operator->()
存在,如果运算符被选为最佳运算符 通过过载解决机制 (13.3( 实现匹配功能。
(强调我的(
在您的情况下,x
是foo
的,m
是a()
的,现在,Synchronized
重载operator->
,foo->a()
相当于:
(foo.operator->())->a();
foo.operator->()
是你在类 Synchronized
中的重载,它返回一个LockedPtr
,然后LockedPtr
调用自己的operator->
。
问问自己:它还能怎么可能表现?
请记住,重载operator->
的目的是使智能指针类可以使用与原始指针相同的语法。 也就是说,如果您有:
struct S
{
T m;
};
并且您有一个指向S
p
的指针,然后您可以通过p->m
访问S::m
,无论p
是S*
还是某种pointer_class<S>
类型。
使用 ->
和直接调用operator->
之间也有区别:
pointer_class<S> pointerObj;
S* p = pointerObj.operator->();
请注意,如果使用重载->
不会自动降低额外级别,那么p->m
可能意味着什么? 怎么可能使用过载?
- g++的分段错误(在NaN上使用to_string两次时)
- 蛇在C++不会连续转两次
- 检查一个数组是否包含在另一个数组中,以相反的顺序,至少两次
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 我应该如何去缓解两次出现的cin?
- 为什么转换运算符调用复制构造函数两次,而等效函数只调用它一次
- 为什么与<运算符的向量比较会比较每个项目两次?
- 在条件运算符中使用对象两次会产生 UB 吗?
- 重载运算符 new(),为什么构造函数被调用两次?
- 在 c++ 中,如何修改运算符以便在同一语句中连续调用它两次
- 范围分辨率运算符被两次使用
- 为什么在C 中超载邮政增量运算符两次调用构造函数
- C++重载运算符两次,一个返回非常量引用,另一个返回常量引用,首选项是什么
- 为什么编译器调用 -> 运算符两次
- 尝试将矩阵与常数重载运算符相乘两次
- 重载 * 乘法运算符两次作为成员函数
- 用不同的参数重载运算符两次
- 毁灭战士 3 来源:为什么表示 2 向量的类会重载下标运算符两次
- 类成员运算符new,调用构造函数两次
- Destructor被调用两次,而没有复制构造函数或赋值运算符被调用