gpt4 book ai didi

c++ - memcmp 与多重相等比较

转载 作者:IT老高 更新时间:2023-10-28 21:39:10 25 4
gpt4 key购买 nike

前提条件 : 考虑这样一个类或结构 T ,对于两个对象 ab类型 T

memcmp(&a, &b, sizeof(T)) == 0

产生相同的结果
a.member1 == b.member1 && a.member2 == b.member2 && ...

( memberNT 的非静态成员变量)。

问题 : 什么时候应该 memcmp用于比较 ab为了平等,什么时候应该链接 ==可以使用吗?

这是一个简单的例子:
struct vector
{
int x, y;
};

重载运算符 ==vector ,有两种可能性(如果它们保证给出相同的结果):
bool operator==(vector lhs, vector rhs)
{ return lhs.x == rhs.x && lhs.y == rhs.y; }

或者
bool operator==(vector lhs, vector rhs)
{ return memcmp(&lhs, &rhs, sizeof(vector)) == 0; }

现在,如果要向 vector 添加新成员,例如 z成分:
  • == s 用于实现 operator== ,必须修改。
  • memcmp改为使用,operator==根本不需要修改。

  • 但我认为使用链式 == s 传达了更清晰的含义。虽然对于大 T拥有众多成员(member) memcmp更诱人。此外,使用 memcmp 是否有性能提升?在 == ?还有什么要考虑的吗?

    最佳答案

    关于memcmp的前提与 == 的成员比较产生相同的结果,虽然这个先决条件在实践中经常得到满足,但它有点脆弱。

    理论上,更改编译器或编译器选项可以打破该先决条件。更值得关注的是,代码维护(所有编程工作的 80% 都是维护,IIRC)可以通过添加或删除成员、使类多态、添加自定义 == 来破坏它。重载等。正如其中一条评论中所提到的,前提条件可以适用于静态变量,而不适用于自动变量,然后创建非静态对象的维护工作可以做坏事™。

    以及关于是否使用memcmp的问题或成员(member)==实现 ==运算符对于类,首先,这是一个错误的二分法,因为这些不是唯一的选择。

    例如,就 compare 而言,使用关系运算符重载的自动生成可以减少工作量并且更易于维护。功能。 std::string::compare函数就是这种函数的一个例子。

    其次,选择哪种实现的答案在很大程度上取决于您认为重要的内容,例如:

  • 应该寻求最大化运行效率 , 或
  • 应该寻求创造最清晰的代码 , 或
  • 应该寻求最简洁的,最快写代码,或
  • 应该努力使类(class)最多保险箱 使用,或
  • 别的,也许?

  • 生成关系运算符。

    您可能听说过 CRTP,Curiously Recurring Template Pattern。我记得它是为了处理生成关系运算符重载的需求而发明的。不过,我可能会将其与其他内容混为一谈,但无论如何:
    template< class Derived >
    struct Relops_from_compare
    {
    friend
    auto operator!=( const Derived& a, const Derived& b )
    -> bool
    { return compare( a, b ) != 0; }

    friend
    auto operator<( const Derived& a, const Derived& b )
    -> bool
    { return compare( a, b ) < 0; }

    friend
    auto operator<=( const Derived& a, const Derived& b )
    -> bool
    { return compare( a, b ) <= 0; }

    friend
    auto operator==( const Derived& a, const Derived& b )
    -> bool
    { return compare( a, b ) == 0; }

    friend
    auto operator>=( const Derived& a, const Derived& b )
    -> bool
    { return compare( a, b ) >= 0; }

    friend
    auto operator>( const Derived& a, const Derived& b )
    -> bool
    { return compare( a, b ) > 0; }
    };

    鉴于上述支持,我们可以调查可用于您的问题的选项。

    实现A:减法比较。

    这是一个提供全套关系运算符的类,不使用 memcmp== :
    struct Vector
    : Relops_from_compare< Vector >
    {
    int x, y, z;

    // This implementation assumes no overflow occurs.
    friend
    auto compare( const Vector& a, const Vector& b )
    -> int
    {
    if( const auto r = a.x - b.x ) { return r; }
    if( const auto r = a.y - b.y ) { return r; }
    return a.z - b.z;
    }

    Vector( const int _x, const int _y, const int _z )
    : x( _x ), y( _y ), z( _z )
    {}
    };

    实现 B:通过 memcmp 进行比较.

    这是使用 memcmp 实现的同一个类;我想你会同意这段代码可以更好地扩展并且更简单:
    struct Vector
    : Relops_from_compare< Vector >
    {
    int x, y, z;

    // This implementation requires that there is no padding.
    // Also, it doesn't deal with negative numbers for < or >.
    friend
    auto compare( const Vector& a, const Vector& b )
    -> int
    {
    static_assert( sizeof( Vector ) == 3*sizeof( x ), "!" );
    return memcmp( &a, &b, sizeof( Vector ) );
    }

    Vector( const int _x, const int _y, const int _z )
    : x( _x ), y( _y ), z( _z )
    {}
    };

    实现C:逐个成员比较。

    这是一个使用成员比较的实现。它不强加任何特殊要求或假设。但它更多的是源代码。
    struct Vector
    : Relops_from_compare< Vector >
    {
    int x, y, z;

    friend
    auto compare( const Vector& a, const Vector& b )
    -> int
    {
    if( a.x < b.x ) { return -1; }
    if( a.x > b.x ) { return +1; }
    if( a.y < b.y ) { return -1; }
    if( a.y > b.y ) { return +1; }
    if( a.z < b.z ) { return -1; }
    if( a.z > b.z ) { return +1; }
    return 0;
    }

    Vector( const int _x, const int _y, const int _z )
    : x( _x ), y( _y ), z( _z )
    {}
    };

    实现 D: compare在关系运算符方面。

    这是一种通过实现 compare 来逆转事物自然顺序的实现方式。在 < 方面和 == ,直接提供并按照 std::tuple实现比较(使用 std::tie )。
    struct Vector
    {
    int x, y, z;

    friend
    auto operator<( const Vector& a, const Vector& b )
    -> bool
    {
    using std::tie;
    return tie( a.x, a.y, a.z ) < tie( b.x, b.y, b.z );
    }

    friend
    auto operator==( const Vector& a, const Vector& b )
    -> bool
    {
    using std::tie;
    return tie( a.x, a.y, a.z ) == tie( b.x, b.y, b.z );
    }

    friend
    auto compare( const Vector& a, const Vector& b )
    -> int
    {
    return (a < b? -1 : a == b? 0 : +1);
    }

    Vector( const int _x, const int _y, const int _z )
    : x( _x ), y( _y ), z( _z )
    {}
    };

    正如给定的,客户端代码使用例如 >需要一个 using namespace std::rel_ops; .

    替代方案包括将所有其他运算符添加到上述(更多代码),或使用 CRTP 运算符生成方案,根据 < 实现其他运算符和 = (可能效率低下)。

    实现E:通过手动使用 <进行比较和 == .

    这个实现是没有应用任何抽象的结果,只是敲击键盘并直接写机器应该做什么:
    struct Vector
    {
    int x, y, z;

    friend
    auto operator<( const Vector& a, const Vector& b )
    -> bool
    {
    return (
    a.x < b.x ||
    a.x == b.x && (
    a.y < b.y ||
    a.y == b.y && (
    a.z < b.z
    )
    )
    );
    }

    friend
    auto operator==( const Vector& a, const Vector& b )
    -> bool
    {
    return
    a.x == b.x &&
    a.y == b.y &&
    a.z == b.z;
    }

    friend
    auto compare( const Vector& a, const Vector& b )
    -> int
    {
    return (a < b? -1 : a == b? 0 : +1);
    }

    Vector( const int _x, const int _y, const int _z )
    : x( _x ), y( _y ), z( _z )
    {}
    };

    选择什么。

    考虑最重要的可能方面的列表,例如安全性、清晰度、效率、简短性,评估上述每种方法。

    然后选择对您来说显然最好的方法,或者看起来同样最好的方法之一。

    指导:为了安全起见,您不会选择方法 A,减法,因为它依赖于对值的假设。请注意,还有选项 B, memcmp , 作为一般情况的实现是不安全的,但仅适用于 ==!= .为了效率,你应该更好 测量 , 以及相关的编译器选项和环境,并记住 Donald Knuth 的格言:“过早的优化是万恶之源”(即花时间在上面可能会适得其反)。

    关于c++ - memcmp 与多重相等比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28858359/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com