use memcmp to compare objects?

来源:互联网 发布:安徽边锋网络综艺大pk 编辑:程序博客网 时间:2024/05/16 19:07
I came across a question regarding c++, is it more efficient to use memcmp to determine equality of two objects of the same type.
This is not a question regarding efficiency at all, it's about correctness. Using memcmp to compare two objects MAY be correct sometimes, but it really depends on several factors:
  1. Class alignment
  2. Compiler implementation
  3. Compiler configuration
You may get different results when work with different types, with different compilers. Even worse, you may get different results between two invocations in the same environment. Though it seems to be efficient, it's not reliable.

We know many compiler will align a class's members to word size for better performance, because it's harder to read or write memories at arbitrary location. So possibly, there are gaps (unused memories) between fields.

Those gaps are occupied by objects of the class, but are note directly managed through objects. The contents of these gaps are undefined. They may be what's left over since their last usage. Or they might be cleared/filled by a diligent compiler.
When you use memcmp to compare two objects, these gaps which has random bits are also taken into considertion. But this is undesired behavior and leads to uncertainty.

So, never do this unless you're 100% sure about the memory layout, compiler behavior, and you really don't care portability, and you really want to gain the efficiency.

The demo below shall show using memcmp doesn't work correctly with microsoft's c++ compiler v15.00.30729.01 and gcc v4.4.1.


#include "string.h"
// ==================================
// Class: Foo
// Description:
// ==================================
class Foo
{
public:
Foo (): a(0), b(0), c(0){
}; // constructor
int a;
char b;
int c;

}; // ----- end of class Foo -----

void shuffle_stack()
{
Foo f1;
Foo f2;

*((int*)(&f1.b)) = 0x87654321;
*((int*)(&f2.b)) = 0x12345678;
}

int compare()
{
Foo f1;
Foo f2;

return memcmp((void*)(&f1), (void*)(&f2), sizeof(Foo));
}

int main ( int argc, char *argv[] )
{
int rc = 0;
shuffle_stack();
rc = compare();
return 0;
} // ---------- end of function main ----------