C++ - 为什么要根据 op+= 而不是相反的方式来实现 op+?
C++ - why implement op+ in terms of op+= and not the other way around?
为什么要这样实现:
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;
}
我在阅读的文献中看到人们多次以这种方式实现它,而从来没有相反的方式,这到底是有什么原因吗,或者这只是一个偶然的巧合?
operator+
必须创建一个新对象来保存结果。 operator+=
不需要新对象。
如果你用 operator+
来写 operator+=
,那么你最终会为额外的新对象创建、赋值(或交换)和销毁付出代价,所有这些你都没有不需要。
除此之外,在许多处理器上,硬件直接支持 +=
和类似的操作,其中结果存储回输入寄存器之一,none 存储到第三个注册(如 +
)。
顺便说一句,您的(原始的,现已编辑的)代码中存在一个错误,隐藏了部分额外工作。您实际上需要:
T& T::operator+=( const T& rhs )
{
*this = *this + rhs; // creation of temporary, move assignment, and destruction of temporary
return *this;
}
更糟糕的是,您的(又是原创的,现在已编辑)建议的 operator+
实施未能正确 return 新对象,它 return 是一个悬空引用。那是未定义的行为。
对于那些感兴趣的人,第一个 operator+
实现可以通过使用按值传递进一步改进:
T operator+( T lhs, const T& rhs )
{
lhs += rhs;
return lhs;
}
现在如果 operator+
的左手操作数是临时的,将使用移动构造函数,避免复制。尽管使用 NRVO,但无论哪种方式,结果代码可能都没有太大优势。
为什么要这样实现:
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;
}
我在阅读的文献中看到人们多次以这种方式实现它,而从来没有相反的方式,这到底是有什么原因吗,或者这只是一个偶然的巧合?
operator+
必须创建一个新对象来保存结果。 operator+=
不需要新对象。
如果你用 operator+
来写 operator+=
,那么你最终会为额外的新对象创建、赋值(或交换)和销毁付出代价,所有这些你都没有不需要。
除此之外,在许多处理器上,硬件直接支持 +=
和类似的操作,其中结果存储回输入寄存器之一,none 存储到第三个注册(如 +
)。
顺便说一句,您的(原始的,现已编辑的)代码中存在一个错误,隐藏了部分额外工作。您实际上需要:
T& T::operator+=( const T& rhs )
{
*this = *this + rhs; // creation of temporary, move assignment, and destruction of temporary
return *this;
}
更糟糕的是,您的(又是原创的,现在已编辑)建议的 operator+
实施未能正确 return 新对象,它 return 是一个悬空引用。那是未定义的行为。
对于那些感兴趣的人,第一个 operator+
实现可以通过使用按值传递进一步改进:
T operator+( T lhs, const T& rhs )
{
lhs += rhs;
return lhs;
}
现在如果 operator+
的左手操作数是临时的,将使用移动构造函数,避免复制。尽管使用 NRVO,但无论哪种方式,结果代码可能都没有太大优势。