c++ - 重载比较运算符失败 [C++11]

标签 c++ c++11 comparison compare operator-overloading

我有一个带有两个重载比较运算符 (operator==) 的 RGB 颜色类。 一种用于 self 类型,一种用于 int (HEX)。

// this one assigns the value correctly
RGB     RGB::operator=(const int hex)
{
    this->r = (hex>>16 & 0xFF) / 255.0f;
    this->g = (hex>>8  & 0xFF) / 255.0f;
    this->b = (hex     & 0xFF) / 255.0f;
    return *this;
}
//--------------------------------------------------------------------------------------
// also works
bool    RGB::operator==(const RGB &color)
{
    return (r == color.r && g == color.g && b == color.b);
}
// this is evil
bool    RGB::operator==(const int hex)
{
    float rr = (hex>>16 & 0xFF) / 255.0f;
    float gg = (hex>>8  & 0xFF) / 255.0f;
    float bb = (hex     & 0xFF) / 255.0f;

    // if i uncomment these lines then everything is fine
    //std::cout<<r<<" "<<rr<<std::endl;
    //std::cout<<g<<" "<<gg<<std::endl;
    //std::cout<<b<<" "<<bb<<std::endl;

    return (r == rr &&
            g == gg &&
            b == bb);
}

RGB::RGB(int hex) 
{ 
  setHex(hex); 
} 

inline void RGB::setHex(unsigned hex) 
{ 
  r = (float)(hex >> 16 & 0xFF) / 255.0f; 
  g = (float)(hex >> 8 & 0xFF) / 255.0f; 
  b = (float)(hex & 0xFF) / 255.0f; 
}

...然后我在 main.cpp 中比较:

RGB a = 0x555555;
bool equals = (a == 0x555555); // returns false

我不知道会发生什么。比较返回 false,但如果我取消注释定义中的 std::cout 行,则该函数按预期工作并返回 true。

这也没有问题:

RGB a = 0x555555;
RGB b = 0x555555;
bool equals = (a == b); // returns true

有人有想法吗?

最佳答案

你不应该在没有优化的情况下获得浮点比较效果。这是因为您在这两种情况下具有相同的功能。

没有优化,以下是正确的:

float func(float);
float a = ...;
func(a) == func(a); //< always true

这就是您所拥有的,您的功能是移位并除以 255。

但是 - 对于优化,情况就不同了。 GCC 具有可以重新排列表达式的优化(参见例如 -freciprocal-math、-fassociative-math)。

在你的情况下,你有:

float rr = (X) / 255.0f;
...
r == rr

例如,它可以在优化后做一些相当于这样的事情:

255.0f * r == (X)

这现在确实受到浮点比较效应的影响。但是,通过在中间引入标准输出,您迫使它对表达式求值更接近它们的书写方式,这再次让您回到对同一函数自身求真值的理智状态。

您可以更改类的定义以将值存储为整数并仅在需要 float 时转换为 float ,或者同时存储十六进制表示和 float 并使用十六进制进行比较。或者您可以使用大于/小于而不是双等于来比较测试两个浮点值是否在彼此的 1/255 以内。例如。像这样:

return (abs(r - rr) < 1/255.0f && ...);

关于c++ - 重载比较运算符失败 [C++11],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17369984/

相关文章:

c++ - boost::spirit (qi) float 和 double 之间的决定

c++ - 无法 `open` 文件,但 `lseek` 已完成且没有错误

c++ - C++中的复制构造函数

c++ - dynamic_pointer_cast 意外行为

c++ - 将指针/引用转换为固定数组大小是否合法

c++ - 弹出并插入堆栈

c++ - 包装递归可变参数模板类会改变行为。为什么?

sql - 如何在 SQL Server 中的 where 子句中比较 varbinary

Python魔术方法混淆

java - 这个比较器是如何工作的?