鉴于这样的课程:
class Vec{
int comp[2];
public:
void add(Vec& vec, Vec& vec2){
comp[0] = vec.comp[0] + vec2.comp[0];
comp[1] = vec.comp[1] + vec2.comp[1];
}
Vec operator+ (Vec& vec){
Vec res;
res.comp[0] = comp[0] + vec.comp[0];
res.comp[1] = comp[1] + vec.comp[1];
return res;
}
};
有两个成员函数基本上做同样的事情,即将两个Vec
加在一起。当然,不同之处在于add
函数中没有涉及中间值,而operator+
声明了Vec
的本地对象。
我的问题是,有没有办法将operator+
与operator=
结合使用,使其具有与add
相同的语义,没有中间值?理由是减少所涉及的中间值的数量,以提高效率,同时保持operator
语法的优雅。
GMP库的C ++接口显然能够做到这一点:http://gmplib.org/manual/C_002b_002b-Interface-General.html#C_002b_002b-Interface-General
该实现的一个重要特征是像a = b + c这样的表达式会导致对相应mpz_add的单次调用,而不会对b + c部分使用临时值。
我想知道是否有可能这样做,或者GMP是否必须使用某种解决方法呢?
答案 0 :(得分:1)
我认为没有真正的优势,因为你的对象非常小。但是对于像动态分配的大型向量这样的东西,这可能很有用。
实现它的一种方法是创建一个临时的noop类来保存未评估的表达式。此类可以转换为Vec,以便它对用户透明。关键是你现在可以为add表达式创建一个专门的operator =。一些代码(填补空白):
struct VecAdd;
struct Vec
{
Vec& operator=(const VecAdd& vecadd) { /*...*/ }
};
struct VecAdd
{
const Vec& v1;
const Vec& v2;
operator Vec() { return Vec(/*...*/); } // for things like: f(v+u);
};
VecAdd operator+(const Vec& a, const Vec& b) { return VecAdd{a, b}; }
这就是GMP实际上做的事情。但是有很多宏和模板可以使代码重复性降低。
答案 1 :(得分:1)
这是一个坏主意,因为它违反了大多数人对操作员行为的自然假设。
不幸的是,它也非常重要(特别是像gmpxx
这样的库,它们想要使用运算符提供自然代码,高性能,并且有大量对象作为参数)。他们是如何做到这一点的?通过使用表达式模板,他们可以在编译时优化表达式。这个想法是运算符不直接返回值,而是返回表达式类的具体实例,然后可以使用元编程来操作它们。
表达式模板是一个相当高级的主题,您应该相对确定它将为您的代码带来显着的好处。在您的示例中,向量的大小不够相关。
答案 2 :(得分:0)
operator+=
如何用作myVec += otherVec