2016-07-25 58 views
2

这是为什么执行:C++ - 为什么要op + =而不是其他方式实现op +?

T& T::operator+=(const T&) { 
    // ... implementation ... 
    return *this; 
} 

T operator+(const T& lhs, const T& rhs) { 
    T temp(lhs); 
    return temp += rhs; 
} 

传播更多的时候比这一个:

T& T::operator+=(const T& rhs) { 
    *this = *this + rhs; 
    return *this; 
} 

T operator+(const T& lhs, const T& rhs) { 
    // ... implementation ... 
    return some_result; 
} 

没有任何理由可言,还是仅仅是我见过的人实现它随机的巧合这种方式多次在我阅读的文献中,而且从来没有其他方式?

+0

测试第二个,你会发现它不起作用。究竟它是如何工作的将取决于'// ...实现...'中发生了什么,但它不会起作用。最有可能的是,'return * this + rhs;'完全不会对'this'做任何事情。 – user2357112

+0

@ user2357112:我的回答是解释你发现的问题,还是另一个? –

+1

请不要通过查看答案来更改帖子。它会使答案无效 – P0W

回答

9

operator+必须创建一个新对象来保存结果。 operator+=不需要新的对象。

如果您按照operator+编写operator+=,那么您最终将支付额外的新对象创建,分配(或交换)和销毁,所有这些都不需要。除此之外,在许多处理器上,硬件直接支持+=和类似的操作,其中结果存储回输入寄存器之一,而不存储到第三寄存器(如+)。

顺便说一句,你的(原来的,现在编辑的)代码隐藏了部分额外工作中的错误。实际上,你需要:

T& T::operator+=(const T& rhs) 
{ 
    *this = *this + rhs; // creation of temporary, move assignment, and destruction of temporary 
    return *this; 
} 

更糟的是,你的(再次原来,现在编辑)建议实施的operator+未能正确地返回新的对象,它返回一个悬挂引用来代替。这是未定义的行为。


对于那些有兴趣,第一operator+实现可以进一步通过使用改进的传递按值:

T operator+(T lhs, const T& rhs) 
{ 
    lhs += rhs; 
    return lhs; 
} 

现在,如果的operator+左手操作数是一个暂时的,移动的构造将被使用,避免副本。尽管使用NRVO,但在任何结果代码中都没有太多优势。

+0

但是,我们不要创建一个新的对象吗?我们在一个案例中创建T temp,并在另一个案例中创建some_result。它是不是归结为同一件事? –

+1

@EnnMichael:在运算符+ =的直接实现中没有任何东西可以创建一个新对象。考虑'std :: complex ',它看起来就像'T&std :: complex :: operator + =(const std :: complex &rhs){re + = rhs.re; im + = rhs.im;返回*这个; }'没有创建新的临时对象,每条语句都完全映射到单个CPU指令(在通用体系结构上)。 –

+1

@EnnMichael:如果您询问'operator +'(而不是'+ =')的变体是否创建临时对象,是的,这是必要的。这也是我的答案开始说的。您建议的方法存在的问题效率极低,“+ =”。 –

相关问题