0%

C++证明为什么operator==不能用memcmp实现

问: 结构体重载 operator== 能否直接使用 memcmp 实现?

1
2
3
4
5
6
7
8
9
10
struct obj
{
/// 这样实现是否正确
bool operator==(const obj& other) const
{
return memcmp(this, &other, sizeof(other)) == 0;
}

...
};

先说结论:不可以。

理由为:

  1. POD 类型的结构体,拥有容器类型的成员中可能存在动态内存,其地址肯定不一样,但内容可能一样,因此不能直接使用 memcmp 来比较。
  2. POD 类型,数组中没有被赋值的垃圾值,会影响内存比较结果。如果保存了指针又想要比较指针指向的内容是否一致,则也不能直接使用 memcmp 来比较。

见如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <cassert>

struct obj
{
bool operator==(const obj& other) const
{
return memcmp(this, &other, sizeof(other)) == 0;
}

unsigned ulUserID;
char acName[32];
unsigned ulDCType;
};

int main()
{
obj st;
obj st1;

assert(st == st1); ///< 无法通过

st.ulUserID = 1;
st.ulDCType = 1;
st.acName[0] = 'a';
st1.ulUserID = 1;
st1.ulDCType = 1;
st1.acName[0] = 'a';
assert(st == st1); ///< 无法通过

return 0;
}

解决办法:

C++11 以前:

1
2
3
4
5
6
7
8
9
10
11
12
13
struct obj
{
bool operator==(const obj& other) const
{
return ulUserID == other.ulUserID
&& ulDCType == other.ulDCType
&& strcmp(acName, other.acName, sizeof(acName)) == 0;
}

unsigned ulUserID;
char acName[32];
unsigned ulDCType;
};

C++11 以后 C++20 以前:

1
2
3
4
5
6
7
8
struct obj
{
bool operator==(const obj& other) const = default;

unsigned ulUserID;
char acName[32];
unsigned ulDCType;
};

C++20 以后:

struct obj
{
    auto operator<=>(const obj&) const = default;

    unsigned ulUserID;
    char acName[32];
    unsigned ulDCType;
};