有人可以请示例解释为什么在C++中重载逗号,地址,逻辑和和逻辑OR运算符不是一个好习惯吗?为什么逗号,地址 - ,逻辑AND和逻辑OR运算符不应该在C++中重载?
回答
如果有人读取代码并看到if(a && b)
,他/她会怎么想?
如果a和b是原生类型,如bool
或int
,则每个人都知道它是如何工作的。
如果它们是类对象,大多数人会希望在应用&&
之前,该类提供了一个operator bool()
或类似的查询它应该是什么bool。没有人会认为这是一种“幻想”的方式来编写if(a.myMethod(b))
,没有人愿意检查类定义=>每个人都会误解和/或混淆状态的目的是什么。
tldr,请勿将内置的&&
用作无关方法调用的缩写。
同样是有效的||
和,
。
至于地址运算符,除了读取混淆问题之外,在编写代码时也很常见:指针地址通常可以为任何类型的变量获取,并且在执行此操作之前,没有人会检查您的类定义。
而且可读性等等,如果以什么顺序的参数赋值不同:
为if(a&&b)
正常,如果是false
,b
甚至没有检查了,因为整个条件只能是假。如果你有像例如。 if(a && func1()) func2();
其中返回值func2()
很重要,func1()
被执行只有如果a
是true
,并且只有两者都为真时才会执行func2()
。超载&&
,func1()
为总是执行。取决于它的作用,这可能不是你想要的。
随着||
,这是类似的:如果第一个参数是true
,第二个参数通常不会看着了,因为整个条件为真,反正。有了过载,参数总是被评估。
正常的逗号运算符a,b
有保证a
在b
之前被评估/执行;过载时可以按任何顺序。
代码可读性是一个问题。但是如果你检查这个链接https://www.securecoding.cert.org/confluence/display/cplusplus/DCL10-CPP.+Do+not+overload+the+ampersand,+comma,+logical+AND+or+logical + OR +操作符,这里解释的原因对我来说很难理解。所以,我问了这个现在被低估的问题。 – bornfree
@bornfree我不是在说可读性。 ...关于您的链接,我将补充说明...... – deviantfan
潜在的原因是这些运算符的重载版本的行为与内建版本的行为不同。这会导致(人类)阅读/编写代码的实质性混乱。
逻辑运算符
&&
和||
的内置版本呈现短路优化:在像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()
代码无法知道这或运营商将被使用。 使用std::addressof
与ptr2
相比可以避免此问题,即使type
运算符有重载&
,该问题也会获得内建运算符地址的等效值。
根据[CWG1458](http://wg21.link/CWG1458),'运营商&案例现在未指定。 –
谢谢@ T.C。将修改我的答案 – Walter
- 1. C++运算符重载逻辑opertors
- 2. 逻辑运算符Objective-C
- 3. 逻辑运算符
- 4. C++逻辑运算符Q
- 5. 逻辑运算符
- 6. 逻辑运算符||
- 7. 重载逻辑运算符被认为是不好的做法?
- 8. 逻辑&&运算符
- 9. 逻辑运算
- 10. 什么是NOR逻辑运算符?
- 11. Spring SpEL逻辑运算符
- 12. 如何有多个“和”逻辑运算符和“或”逻辑运算符
- 13. 逻辑AND运算符
- 14. C++逻辑与运算
- 15. Java逻辑运算符
- 16. 逻辑比较运算符
- 17. 结合逻辑运算符C
- 18. C#中逻辑运算符的结构#
- 19. 2列的逻辑运算(逻辑或)
- 20. C# - 解析包含逻辑运算符
- 21. 逻辑与运算符与
- 22. 为什么C没有逻辑赋值运算符?
- 23. 逻辑和虚拟地址
- 24. 使用(逻辑):运算符C#
- 25. 逻辑比较==运算符过载
- 26. 不同的逻辑地址
- 27. PowerShell逻辑运算符和$ Error变量
- 28. 重载运算符C++的逻辑错误
- 29. 被C++逻辑OR(||)运算符困惑
- 30. ATT装配(算术和逻辑运算)
如果您重载了逗号运算符,那么您就是STL将其C++ STL实现更改为在适当情况下执行'a,void(),b'的原因。 – chris
我不认为这个问题应该被视为'主要基于意见' – Walter
谁说的和什么时候? –