有人可以用例子解释为什么在c ++中重载逗号,地址,逻辑AND和逻辑OR运算符不是一个好习惯吗?
答案 0 :(得分:6)
潜在的原因是这些运算符的重载版本的行为与内置版本不同。这可能导致(人类)读/写代码的大量混淆。
逻辑运算符&&
和||
内置版本展示短路优化:在a && b
这样的表达式中,a
首先进行评估,且仅在评估true
,b
时进行评估;类似地,在a || b
中,a
首先进行评估,并且仅在评估false
,b
时进行评估。重载运算符&&
和||
没有短路优化(始终评估a
和b
)并且未指定参数的评估顺序
逗号运算符内置版本保证参数按其出现的顺序进行评估,即首先评估a,b
a
b
}。使用重载的逗号运算符,此保证将丢失(而功能参数机制将起作用)。
运营商地址运营商&
的内置地址与应用于不完整类型对象时的重载地址之间可能存在混淆。考虑一下这段代码
struct type; // forward declaration: type is (as of yet) incomplete
#include <memory>
void foo(type &obj) // allowed: take object of incomplete type by reference
{
auto ptr1 = &obj; // address of obj -- or not?
auto ptr2 = std::addressof(obj); // always address of obj
}
// possibly in a different translation unit:
struct type
{
type* operator&() { return nullptr; }
};
此代码展示unspecified behaviour:编译器可以在&
中实现foo()
运算符的任一版本,但编写foo()
代码的人无法知道这个或哪个将使用运算符。
使用ptr2
和type
时可以避免此问题,即使&
有一个重载{{1}}运算符,它也会获得内置地址运算符的等价物。
答案 1 :(得分:4)
如果有人读取代码并看到if(a && b)
,他/她会怎么想?
如果a和b是本地类型,如bool
或int
,则每个人都知道它是如何工作的。
如果它们是类对象,那么在应用operator bool()
之前,大多数人都会期望该类提供&&
或类似的查询它应该是什么样的bool。没有人会期望它是一个“花哨的”#34;写if(a.myMethod(b))
的方法,并且无人将检查类定义=&gt;每个人都会误解和/或混淆条件的目的是什么
tldr,不要使用内置&&
作为无关方法调用的缩写。
同样适用于||
和,
。
对于地址运算符,除了读取混淆问题之外,它在编写代码时也非常存在:通常可以为任何类型的任何变量获取指针地址,没有人会检查你的类定义在做之前。
除了可读性等,如果评估参数的顺序和顺序不同:
对于if(a&&b)
通常,如果a false
,则b
甚至不再被检查,因为整个条件只能是假的。如果你有像这样的东西。 if(a && func1()) func2();
的返回值func2()
很重要,func1()
仅在a
为true
时才会执行,且只有两者都是func2()
执行true &&
。在重载func1()
时,||
总是执行。根据它的作用,这可能不是你想要的。
使用true
,它类似:如果第一个参数是 a,b
,则第二个参数通常不再被查看,因为无论如何,整个条件都是真的。过载时,始终会评估参数。
普通逗号运算符a
具有在b
之前评估/执行android:configChanges="orientation|screenSize"
的保证;超载它可以是任何顺序。