我假设operator+的规范形式,假设存在重载的operator+=成员函数,是这样的:
const T operator+(const T& lhs, const T& rhs)
{
return T(lhs) +=rhs;
}
但有人向我指出,这也是可行的:
const T operator+ (T lhs, const T& rhs)
{
return lhs+=rhs;
}
本质上,这种形式将临时的创建从函数调用的实现主体。
两个参数的类型不同似乎有点尴尬,但是第二种形式有什么问题吗? 有理由选择其中一种而不是另一种吗?
I had assumed that the canonical form for operator+, assuming the existence of an overloaded operator+= member function, was like this:
const T operator+(const T& lhs, const T& rhs)
{
return T(lhs) +=rhs;
}
But it was pointed out to me that this would also work:
const T operator+ (T lhs, const T& rhs)
{
return lhs+=rhs;
}
In essence, this form transfers creation of the temporary from the body of the implementation to the function call.
It seems a little awkward to have different types for the two parameters, but is there anything wrong with the second form? Is there a reason to prefer one over the other?
发布评论
评论(7)
我不确定生成的代码是否有很大差异。
在这两者之间,我(个人)更喜欢第一种形式,因为它更好地传达了意图。 这是关于 += 运算符的重用和通过 const& 传递模板化类型的习惯用法。
I'm not sure if there is much difference in the generated code for either.
Between these two, I would (personally) prefer the first form since it better conveys the intention. This is with respect to both your reuse of the += operator and the idiom of passing templatized types by const&.
对于编辑后的问题,首选第一种形式。 编译器更有可能优化返回值(您可以通过在 T 的构造函数中放置断点来验证这一点)。 第一种形式也将两个参数都视为 const,这将是更理想的。
研究返回值优化主题,例如此链接作为快速示例:http://www.cs.cmu.edu/~gilpin/c++/performance.html
With the edited question, the first form would be preferred. The compiler will more likely optimize the return value (you could verify this by placing a breakpoint in the constructor for T). The first form also takes both parameters as const, which would be more desirable.
Research on the topic of return value optimization, such as this link as a quick example: http://www.cs.cmu.edu/~gilpin/c++/performance.html
为了可读性,我更喜欢第一种形式。
在看到第一个参数被复制之前,我必须三思而后行。我没想到会这样。 因此,由于这两个版本可能同样有效,我会选择一个更容易阅读的版本。
I would prefer the first form for readability.
I had to think twice before I saw that the first parameter was being copied in. I was not expecting that. Therefore as both versions are probably just as efficient I would pick them one that is easier to read.
如果你想要简洁,为什么不这样做呢?
why not this if you want the terseness?
我的第一个想法是,第二个版本可能比第一个版本快得多,因为没有引用作为参数推送到堆栈上。 然而,这将非常依赖于编译器,并且取决于例如编译器是否执行命名返回值优化。
无论如何,如果有任何疑问,永远不要选择非常小的性能增益,这种增益甚至可能不存在,而且您很可能不需要 - 选择最清晰的版本,这是第一个版本。
My first thought is that the second version might be infinitessimally faster than the first, because no reference is pushed on the stack as an argument. However, this would be very compiler-dependant, and depends for instance on whether the compiler performs Named Return Value Optimization or not.
Anyway, in case of any doubt, never choose for a very small performance gain that might not even exist and you more than likely won't need -- choose the clearest version, which is the first.
事实上,第二种是首选。 正如 C++ 标准中所述,
也就是说,因为未命名的临时对象是使用复制构造函数创建的,所以编译器可能不会使用返回值优化。 然而,对于第二种情况,允许未命名的返回值优化。 请注意,如果您的编译器实现命名返回值优化,则最好的代码是
Actually, the second is preferred. As stated in the c++ standard,
That is, because an unnamed temporary object is created using a copy constructor, the compiler may not use the return value optimization. For the second case, however, the unnamed return value optimization is allowed. Note that if your compiler implements named return value optimization, the best code is
我认为,如果你将它们都内联(我会这样做,因为它们只是转发函数,并且可能operator+=()函数是外线的),你会得到几乎无法区分的代码生成。 也就是说,第一个更为规范。 第二个版本不必要地“可爱”。
I think that if you inlined them both (I would since they're just forwarding functions, and presumably the operator+=() function is out-of-line), you'd get near indistinguishable code generation. That said, the first is more canonical. The second version is needlessly "cute".