C++中operator+=的auto返回类型推导疑问
关于std::pair的operator+=重载问题解答
1. auto返回类型的推导问题
你当前代码里用auto作为返回类型,不会推导出引用。因为函数返回值的auto推导遵循模板参数推导规则:当返回的是左值引用类型的表达式(比如你的p1是std::pair<T, T2>&),auto会忽略引用属性,推导出值类型std::pair<T, T2>。这意味着你的函数实际上会返回p1的副本,而不是你想要的原对象引用。
要让返回类型是左值引用,有三种可选方式:
- 显式指定返回类型:
std::pair<T, T2>&(最直观,符合运算符重载的常规写法) - 使用
auto&作为返回类型:inline auto& operator+=(... - 使用
decltype(auto):它会根据返回表达式的值类别推导类型,return p1是左值表达式,因此decltype(auto)会推导为std::pair<T, T2>&
其中显式指定返回类型是最推荐的写法,可读性最高,符合C++运算符重载的惯例。
2. operator+=返回右值是否合理?
完全不合理,原因有三点:
- 违背语义惯例:标准库中所有的
operator+=(比如std::string、std::vector的+=)都返回左值引用,目的是表达“修改原对象并返回它”的语义。返回右值(副本)会让使用者误以为修改的是原对象,实际却操作了临时副本,容易引发逻辑错误。 - 破坏链式调用:如果返回右值,像
a += b += c这样的链式调用会失效——b += c返回的是b的副本,然后a和这个副本相加,原b的修改不会传递到后续操作,完全不符合预期。 - 带来性能损耗:返回副本会触发
std::pair的拷贝构造,造成额外的性能开销,尤其是当T或T2是大类型时。
修正后的代码示例
template<typename T, typename T2> inline std::pair<T, T2>& operator+=(std::pair<T, T2>& p1, const std::pair<T, T2>& p2) { auto& [x1, y1] = p1; const auto& [x2, y2] = p2; x1 += x2; y1 += y2; return p1; }
内容的提问来源于stack exchange,提问作者Ilan Keshet
相关产品推荐
相关产品推荐

