自定义类型的运算符优先级,以及当存在多个相同运算符时是否可能进行延迟求值
Operator precedence for custom types and is it possible to have lazy evaluation when multiples of the same operator are present?
假设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
的运算符。所以这个数组被遍历两次。是否有可能有延迟评估执行全局操作时,同一操作符的倍数和/或多个操作符的倍数存在?
编辑:这是一个最小的工作示例。请注意第二个重载中的missing const
,我使用它来与另一个array operator -(const array& other)
重载消除歧义,用于两个数组的逐元素减法。我想这就是第一个问题的原因。
这是因为你的"array - float"操作符没有将数组作为const引用。因此,为2.0 - marray
创建的临时不能绑定到它。在链接到最小的工作示例中,您使用2 - marray - 5
,当编译器生成要减去5的代码时,它将使用接受整数的构造函数构造一个新数组,然后在两个数组成员之间调用减法运算符。
将第二个减法运算符更改为array operator -(const array& lhs, float rhs)
相关文章:
- C++矢量复制构造函数和赋值运算符是否也复制保留空间?
- 复合赋值运算符是否不如 C++ 精确?
- 放置新运算符是否会禁用默认的新运算符?
- C++箭头运算符 (->) 是否在所有情况下都返回左值?
- std::unordered_map 运算符 [] 是否对非现有密钥进行零初始化?
- 在这里使用删除运算符是否正确,我很困惑
- lambda 的调用运算符是否需要具有链接?
- 复制构造函数和复制赋值运算符是否应具有相同的语句?
- "new"运算符是否总是调用构造函数?
- 检查运算符是否在C++中过载
- C++新运算符是否在下面使用 malloc()
- 地址运算符是否返回变量引用的对象的地址
- 链表的这个别名运算符是否会产生深度复制
- cv::P oint3f 赋值运算符是否执行"深度"复制?
- 三向比较运算符是否始终有效
- 在全局命名空间中重载不依赖于用户定义类型的标准定义类型的运算符是否格式正确?
- std::string 的运算符<是否应该受到当前区域设置的影响?
- 关于解引用运算符是否在表达式中产生对象对值的定义不明确
- 运算符是否应该==或!=在这种情况下扔
- 检查 QTextStream::运算符>>是否失败