假设我想为std::vector
提供逐元素的算术运算符operator+=
和operator+
,以便逐个元素地添加向量条目。通常情况下,我会看到operator+
是这样实现的:operator+
利用operator+=
来实现。
#include <algorithm>
#include <vector>
template<class Type>
std::vector<Type> & operator+=(std::vector<Type> &x, const std::vector<Type> &y) {
// Checks for equal size of x and y omitted here...
std::transform(std::begin(x), std::end(x), std::begin(y), std::begin(x), std::plus<Type>());
return x;
}
template<class Type>
std::vector<Type> operator+(std::vector<Type> x, const std::vector<Type> &y) {
// Checks for equal size of x and y omitted here...
return x += y;
}
int main() {
std::vector<double> v0{1.0, 2.0, 3.0};
auto v1 = v0;
auto v2 = v0;
v2 += v0; // yields [2, 4, 6]
auto v3 = v0 + v1; // yields [2, 4, 6]
return 0;
}
就性能而言,我猜想
template<class Type>
std::vector<Type> operator+(const std::vector<Type> &x, const std::vector<Type> &y) {
// Checks for equal size of x and y omitted here...
std::vector<Type> result;
result.reserve(x.size());
std::transform(std::begin(x), std::end(x), std::begin(y), std::back_inserter(result), std::plus<Type>());
return result;
}
第二种方法更有效率,因为在进入函数时避免了初始化第一个参数的副本,而是直接将结果放入未初始化的内存块中。但是,是否值得实现第二个版本,还是可以假设编译器会进行优化呢?另外,我认为第二种选择比第一种不太通用。想象一下类似于以下情况:
#include <array>
#include <type_traits>
template<class Container, class Enable = void>
struct IsSequenceContainer: public std::false_type {
};
template<>
template<class Type, std::size_t size>
struct IsSequenceContainer<std::array<Type, size> >: public std::true_type {
};
template<>
template<class Type, class Allocator>
struct IsSequenceContainer<std::vector<Type, Allocator> >: public std::true_type {
};
// Use the following operations for std::array and std::vector
template<class Container>
typename std::enable_if<IsSequenceContainer<Container>::value, Container>::type operator+(Container x, const Container &y) {
return x += y;
}
operator+
不会被误认为是连接运算符... - Toby Speightstd::valarray
,但实际上我更喜欢std::vector
而不是std::valarray
,例如请参考这个帖子。 - Marceloperator+=
和operator+
的歧义。然而,在我看来,只要你清晰地记录下你的意图并且根据你的应用(例如科学应用程序)确定,提供这样的运算符是完全合法的,即使在不同的上下文中它们可能有着不同的含义。 - Marcelnamespace std;
)找到;并且如果你在另一个任何定义了operator+=
的范围内,它会隐藏这个重载函数。 - M.M