有哪些合理的理由可以重载一元运算符&?

71

好的,我被激励去打一些头。似乎重载operator&会导致不少的痛苦。

有哪些合法的情况可以使用重载呢?

(我从未这样做过....)

6个回答

53

我似乎记得有一个智能指针类,它覆盖了 operator&,因为它想返回包含指针的地址而不是智能指针对象的地址。我不记得在哪里看到过或者当时是否觉得这是个好主意。

啊哈,我记起来了: Microsoft 的 CComPtr

编辑: 要进行概括,可能在以下条件下才有意义:

  • 您有一个伪装成其他对象的对象。
  • 此对象可以获取指向其伪装对象的指针。

返回除合法指针之外的任何内容都将违反最少惊讶原则


1
@Billy,我已经很久没有使用这个了,我也不记得它的优缺点了。由于在COM编程中传递接口指针的地址是一种常见操作,所以似乎是可以辩解的。 - Mark Ransom
“_包含指针的地址_” 您是指包含的指针,对吗? - curiousguy
5
@curiousguy 我不这么认为。所包含的指针类型为“T *”。operator&返回的指针类型为“T **”,并指向所包含的指针。 - user743382
2
CComPtr中的&运算符重载是一种危险的黑客行为。它仅在智能指针未初始化时才能正常工作。否则,它已经持有的对象将无法使其引用计数减少,并且会产生泄漏。在调试版本中,它实际上断言该指针已经为空,因为这种错误太常见了。 - Adrian McCarthy

12

在 lambda 占位符表示法中,当表示 & 操作时很有用,例如: &_1[_2]


10

重载一元运算符&可以使你的对象表现得像一个引用(在这方面)。

我相信尝试提供内置引用的替代方案是徒劳无功的,特别是因为在C++中,引用根本不是对象,它们没有自己的地址。而你定义的类型的实例不可避免地是对象,并且即使你禁用了获取该地址的常规方式,它们也有地址。因此,它永远不会完美地模拟引用。

但是,人们非常热衷于使用用户定义的指针替代方法,所以我能够理解某些人可能想要尝试。我不确定他们是否能避免创建一种(误)行为方式会让其用户后悔的类型。


但是https://isocpp.org/wiki/faq/references#overview-refs说:“尽管引用通常使用底层汇编语言中的地址来实现,请不要将引用视为指向对象的奇怪指针。引用就是对象本身,它不是指向对象的指针,也不是对象的副本。它就是对象。” - Destructor
1
@PravasiMeet:很不幸,他们这样表述,因为标准明确指出引用不是对象。这就像变量的名称一样:变量是一个对象,但它的名称不是。引用的参照物是一个对象,但引用本身不是。 - Steve Jessop
请问您能告诉我明确说明引用不是对象的标准引用吗? - Destructor
1
@PravasiMeet:嗯,我以为有一个明确的陈述,但目前我找不到它,所以也许它并不是明确的。然而,[intro.object]说“对象是存储区域”,而[dcl.ref]在注释中说“引用可以被视为对象的名称”,并规范地说“引用是否需要存储是未指定的”。 - Steve Jessop
同时在常见问题解答中,首先它说“什么是引用?对象的别名(另一个名称)”。因此,如果他们说引用是一个名称,并且引用是对象,那么只要他们说名称就是对象,那么他们就是一致的。然而,就C++标准的行话而言,对象的名称也不是对象。它在表达式中代表对象,这与与对象相同不同,但在英语中,“是”可以表示两种意思。 - Steve Jessop

8

四年后,又有了一个答案。

另一个用途是当您在借鉴C++语言时,但定义自己的语义。最典型的例子:Boost.Spirit。

Boost.Spirit,特别是用于解析的Qi,重载了解析器上的运算符,以提供类似EBNF的语法来指定任意解析器对象。特别地,一元&运算符被重载以提供And-Predicate Parser

And-Predicate Parser (&a)

描述

语法谓词在评估另一个产生式之前断言某个条件语法需要被满足。与语义谓词eps类似,语法谓词不消耗任何输入。and-predicate,&a,是一个正面的语法谓词,只有当它的谓词匹配时才返回零长度匹配。

示例用法:

基本向前看示例:确保最后一个字符是分号,但不要消耗它,只需查看下一个字符:

test_phrase_parser("Hello ;", lit("Hello") >> &lit(';'), false);

简而言之,这里的一元运算符&与指针没有任何关系;它具有特定领域的语义,适用于 Qi 解析器对象。

2
简而言之,这是另一个表达式模板的示例,答案相同。 - sehe

8

我在生成LLVM代码的DSL上做到了很好的效果。以下示例说明。假设xy是值(即类型为value的对象)。那么表达式x+y会向某个代码流中发出ADD指令。相当合理的是,表达式&x会发出一条指令来获取x的地址。


0

曾经我曾将运算符&(不改变其行为)作为类的私有成员进行重载,以保护免受在堆栈中创建智能指针对象的意外情况。但我仍然不确定这是否是一个好主意...


2
这是一个糟糕的想法,因为你没有达到你的目标。请参考:https://dev59.com/YWw15IYBdhLWcg3wntKh - Billy ONeal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接