2015-12-15 57 views
0

有人可以请示例解释为什么在C++中重载逗号,地址,逻辑和和逻辑OR运算符不是一个好习惯吗?为什么逗号,地址 - ,逻辑AND和逻辑OR运算符不应该在C++中重载?

+1

如果您重载了逗号运算符,那么您就是STL将其C++ STL实现更改为在适当情况下执行'a,void(),b'的原因。 – chris

+0

我不认为这个问题应该被视为'主要基于意见' – Walter

+0

谁说的和什么时候? –

回答

4

如果有人读取代码并看到if(a && b),他/她会怎么想?
如果a和b是原生类型,如boolint,则每个人都知道它是如何工作的。

如果它们是类对象,大多数人会希望在应用&&之前,该类提供了一个operator bool()或类似的查询它应该是什么bool。没有人会认为这是一种“幻想”的方式来编写if(a.myMethod(b)),没有人愿意检查类定义=>每个人都会误解和/或混淆状态的目的是什么。
tldr,请勿将内置的&&用作无关方法调用的缩写。

同样是有效的||,

至于地址运算符,除了读取混淆问题之外,在编写代码时也很常见:指针地址通常可以为任何类型的变量获取,并且在执行此操作之前,没有人会检查您的类定义。

而且可读性等等,如果以什么顺序的参数赋值不同:

if(a&&b)正常,如果是falseb甚至没有检查了,因为整个条件只能是假。如果你有像例如。 if(a && func1()) func2();其中返回值func2()很重要,func1()被执行只有如果atrue,并且只有两者都为真时才会执行func2()。超载&&func1()总是执行。取决于它的作用,这可能不是你想要的。

随着||,这是类似的:如果第一个参数是true,第二个参数通常不会看着了,因为整个条件为真,反正。有了过载,参数总是被评估。

正常的逗号运算符a,b有保证ab之前被评估/执行;过载时可以按任何顺序。

+1

代码可读性是一个问题。但是如果你检查这个链接https://www.securecoding.cert.org/confluence/display/cplusplus/DCL10-CPP.+Do+not+overload+the+ampersand,+comma,+logical+AND+or+logical + OR +操作符,这里解释的原因对我来说很难理解。所以,我问了这个现在被低估的问题。 – bornfree

+0

@bornfree我不是在说可读性。 ...关于您的链接,我将补充说明...... – deviantfan

6

潜在的原因是这些运算符的重载版本的行为与内建版本的行为不同。这会导致(人类)阅读/编写代码的实质性混乱。

  1. 逻辑运算符&&||的内置版本呈现短路优化:在像a && b一个表达式,a首先计算且仅当trueb还评价;类似地,在a || b,a中首先被评估,并且只有在false,b也被评估。重载运算符&&||没有短路优化(总是对ab进行评估),也未指定参数计算的顺序。

  2. 逗号运算符的内置版本保证参数在它们发生的顺序,即,在评价a,ba首先计算然后b。在重载逗号运算符的情况下,这个保证将会丢失(而函数参数机制会发挥作用)。

  3. 地址运算符有内建地址运算符&并且当应用于不完整的类型的对象重载一个之间的潜在的混淆。考虑以下代码

    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::addressofptr2相比可以避免此问题,即使type运算符有重载&,该问题也会获得内建运算符地址的等效值。

+0

根据[CWG1458](http://wg21.link/CWG1458),'运营商&案例现在未指定。 –

+0

谢谢@ T.C。将修改我的答案 – Walter