【发布时间】:2015-07-06 07:32:11
【问题描述】:
我正在尝试编写一个 C++ 矢量类,它存储数据数组并允许逐个元素执行数学运算。我想以这样一种方式实现这一点,即表达式 a = b + c + d 应该只遍历所有元素一次,并直接将和 b[i] + c[i] + d[i] 写入 a[i] 而不创建中间向量。
我写的是这样的:
template<class T, int N>
class VectorExpression {
public:
virtual T operator[] (int i) const = 0;
virtual ~VectorExpression() {}
}
template<class T, int N>
class MyVector : public VectorExpression<T, N> {
T data[N];
public:
T& operator[] (int i) { return data[i]; }
T& const operator[] (int i) const { return data[i]; }
MyVector<T,N>& operator=(const VectorExpression<T,N> &rhs) {
for (int i = 0; i < N; ++i)
data[i] = rhs[i];
return *this;
}
}
template<class T, int N>
class VectorSum : public VectorExpression<T, N> {
VectorExpression<T,N> &a, &b;
public:
VectorSum(VectorExpression<T,N> &aa, VectorExpression<T,N> &bb)
: a(aa), b(bb) {}
T operator[] (int i) const { return a[i] + b[i]; }
}
template<class T, int N>
VectorSum<T,N> operator+(const VectorExpression<T,N> &a,
const VectorExpression<T,N> &b)
{
return VectorSum<T,N>(a, b);
}
int main() {
MyVector<double,10> a, b, c, d;
// Initialize b, c, d here
a = b + c + d;
return 0;
}
这个功能可能是由 valarray 类提供的,但那是因为我试图将它简化为一个最小的示例。
我将operator[] 设为虚拟,因为这允许嵌套所有类型的表达式(例如a = !(-b*c + d)),前提是我将定义所有类似于VectorSum 的运算符和相应的类。
我使用引用是因为普通变量不是多态的,并且指针不适用于运算符重载。
现在我的问题是:
在
a = b + c + d;语句中,会创建两个临时的VectorSum<double,10>对象,分别存储b + c和(b+c) + d。它们的寿命是否足以使多态行为发挥作用?更具体地说,(b+c) + d将存储对b + c的引用,但是当调用operator=时该对象是否仍然存在?根据this post,所有临时对象都应该存在,直到operator=返回,但这是否也适用于旧版本的C++?如果不是,那么这是如何完成的?我看到的唯一选择是使用
new分配VectorSum对象,通过引用返回它们,然后在operator=函数中删除它们,但这似乎有点麻烦,而且效率可能低得多。我也不确定它是否总是安全的。(小问题)可以在
MyVector中用T& const覆盖VectorExpression::operator[]的返回类型T吗?
编辑
我在 operator+ 中有错误的参数类型:将它们从 VectorSum 更改为 VectorExpression。
【问题讨论】:
-
这不能回答您的问题,我也没有深入研究您的代码,但我不确定这是实现对您的总和进行有效后期评估的方法。你考虑过使用expression templates 吗?
-
据我了解,您所指的网站与我所做的或多或少相同,只是使用模板而不是继承。我没有想到,所以谢谢。不过,我不太确定哪个选项更好;他们的方法不需要虚拟类,但它确实需要更多的类(特别是如果你在模板实例化之后计算它们)并且所有这些类的临时对象都必须实例化。
-
谢谢!这样代码变得相当复杂,但我现在看到,使用表达式模板,您可以在运行时完全消除所有临时和函数调用,这在使用继承和虚函数时是不可能的。在大多数情况下,这可能使它成为比我更好的解决方案。
标签: c++ reference polymorphism