代码之家  ›  专栏  ›  技术社区  ›  Jon Purdy

这是实现泛型运算符==和运算符<的安全方法吗?

  •  11
  • Jon Purdy  · 技术社区  · 14 年前

    this question ,我的第一个想法是,定义泛型等价和关系运算符很简单:

    #include <cstring>
    
    template<class T>
    bool operator==(const T& a, const T& b) {
    
        return std::memcmp(&a, &b, sizeof(T)) == 0;
    
    }
    
    template<class T>
    bool operator<(const T& a, const T& b) {
    
        return std::memcmp(&a, &b, sizeof(T)) < 0;
    
    }
    

    using namespace std::rel_ops == < . 显然,这不会执行按成员比较,而是按位比较,就好像类型只包含POD成员一样。这与C++如何生成复制构造函数(例如 执行成员复制。

    但我不知道上述实施是否确实安全。结构自然会有相同的包装,属于相同的类型,但是填充的内容是否保证是相同的(例如,用零填充)?有什么原因或情况下,这不会工作?

    6 回复  |  直到 7 年前
        1
  •  6
  •   DumbCoder    5 年前

    永远不要这样做,除非你100%确定内存布局,编译器行为,你真的不在乎可移植性,你真的想获得效率

    SOURCE

        2
  •  13
  •   Jerry Coffin    14 年前

    operator== 不正常。两个NaN永远不应该以相等的方式进行比较,即使它们具有相同的位模式(事实上,检测NaN的一种常见方法是将数字与自身进行比较——如果它不等于自身,则为NaN)。同样,两个浮点数的所有位的指数都设置为0,其值为0.0(精确),而不管有效位中的位是什么。

    operator< std::string 看起来像这样:

    template <class charT>
    class string { 
        charT *data;
        size_t length;
        size_t buffer_size;
    public:
        // ...
    };
    

    操作员< 将根据字符串恰好存储其数据的缓冲区的地址进行比较。例如,如果它碰巧是用 length 首先,比较将使用字符串的长度作为主键。无论如何,它 不会 基于实际的字符串内容进行比较,因为它只会查看 data

    编辑:就填充而言,不要求填充的内容相等。从理论上讲,填充也有可能是某种陷阱表示,它会导致一个信号,抛出一个异常,或者其他类似的顺序,如果你想看它的话。为了避免这种陷阱表示,您需要使用类似cast的方法来将其视为 unsigned char s。 memcmp 可能会这样,但可能不会。。。

    还要注意的是,作为相同类型的对象 必然意味着使用相同对齐的构件。这是一种常见的实现方法,但编译器也完全有可能根据“认为”特定对象将被使用的频率使用不同的对齐方式,并包含某种标记 在里面

    这两种情况都不太可能发生,也不常见,但我想不出标准中有什么禁止它们的。

        3
  •  3
  •   tibur    14 年前

    即使对于POD,==运算符也可能是错误的。这是由于结构的对齐,如下面的一个在我的编译器上占用8字节。

    class Foo {
      char foo; /// three bytes between foo and bar
      int bar;
    };
    
        4
  •  2
  •   John    14 年前

    这是非常危险的,因为编译器不仅会对普通的旧结构使用这些定义,而且会对忘记定义的任何类(无论多么复杂)使用这些定义 == < 适当地。

    总有一天,它会咬你。

        5
  •  0
  •   morechilli    14 年前

    e、 g.如果在类中比较的任何成员都是浮点数。

    通常,这些数字应与适当的公差进行数字比较。

        6
  •  0
  •   Puppy    14 年前

    任何包含单个指针的结构或类都会立即导致任何有意义的比较失败。这些操作符只适用于任何纯旧数据类或POD类。另一位回答者正确地指出了浮点是一种情况,即使它不成立,填充字节。

    简而言之:如果这是一个聪明的想法,那么这种语言会像默认的复制构造函数/赋值操作符一样。