【发布时间】:2015-12-16 06:33:45
【问题描述】:
假设array 是一个自定义类型,定义为本质上管理资源的类
class array {
public:
size_t size;
float *data;
};
为了使operator - 对array 执行元素级标量加法并能够处理array+float 和float+array 的左右关联,我们像这样重载它
array operator -(float lhs, const array& rhs)
{
array tmp(rhs.size);
for (size_t i=0;i<rhs.size;++i)
tmp.data[i] = lhs-rhs.data[i];
return tmp;
}
array operator -(array& lhs, float rhs)
{
array tmp(lhs.size);
for (size_t i=0;i<lhs.size;++i)
tmp.data[i] = lhs.data[i]-rhs;
return tmp;
}
假设我们也有一个initializer_list 构造函数,所以我们可以这样做
array marray = {1.0f,2.0f,3.0f,4.0f};
现在
std::cout << marray-5.0 << "\n";
std::cout << 2.0-marray << "\n";
我们得到了想要的结果,但是这样做
std::cout << 2.0-marray-5.0 << "\n";
甚至没有为marray-5.0 调用第二个重载,并为输出数组的最后两个元素提供了无意义的值,当然2.0-(marray-5.0) 确实解决了问题,但不是通用解决方案。所以问题是:
- 到底发生了什么?为什么根本不调用第二个重载?这是否与运算符优先级有关?
- 我的第二个问题是关于第二种情况的,即
2.0-(marray-5.0),这里我们调用一次float+array的运算符和一次array+float的运算符。所以数组被遍历了两次。当存在多个相同运算符和/或多个运算符的倍数时,是否可以进行惰性评估以一次执行全局操作?
编辑: Here 是一个最小的工作示例。注意第二个重载中的missing const,我用另一个array operator -(const array& other) 重载来消除歧义,用于两个数组的元素减法。我想这是第一个问题的原因。
【问题讨论】:
-
您需要提供一个小而完整的代码示例来展示您的问题。正如尝试流式传输
array(无流式操作符)的代码所展示的那样,您没有证据表明构造函数可以进行大小调整等。任何缺少的东西都可能是贡献者,这让任何人都想提供帮助您处于试图猜测缺少什么的位置。是的,可以进行惰性求值,但这依赖于多个函数(成员、构造函数等)协同工作。 -
我已将链接添加到产生结果的小型工作示例。
-
顺便说一句,尽快切换到
std::vector<float>或std::unique_ptr<float[]>。没有理由手动编写析构函数,并且后一种选项的开销为零。 -
而您正在寻找实现惰性评估的是“表达式模板”模式。它在 C++ 矩阵库中非常流行。
标签: c++ arrays lazy-evaluation operator-precedence associativity