如何在c ++中计算对象的哈希/校验和/指纹?
要求:
该功能必须是“内射”(*)。换句话说,应该没有两个不同的输入对象,它们返回相同的散列/校验和/指纹。
背景:
我正在尝试提出一个简单的模式来检查实体对象自构造以来是否已被更改。 (为了知道需要在数据库中更新哪些对象)。
请注意,我特别不希望在我的setter或其他任何地方将对象标记为已更改。
我正在考虑以下模式:简而言之,每个应该持久化的实体对象都有一个成员函数" bool is_changed()"。在这种情况下,改变意味着改变了对象'构造函数被调用。
注意:我所有这一切的动机是避免将标记对象标记为干净/脏或通过成员比较执行成员时的样板代码。换句话说,减少人为错误的风险。
(警告:提前输入psudo c ++代码。我还没有尝试编译它。)
class Foo {
private:
std::string my_string;
// Assume the "fingerprint" is of type long.
long original_fingerprint;
long current_fingerprint()
{
// *** Suggestions on which algorithm to use here? ***
}
public:
Foo(const std::string& my_string) :
my_string(my_string)
{
original_fingerprint = current_fingerprint();
}
bool is_changed() const
{
// If new calculation of fingerprint is different from the one
// calculated in the constructor, then the object has
// been changed in some way.
return current_fingerprint() != original_fingerprint;
}
void set_my_string(const std::string& new_string)
{
my_string = new_string;
}
}
void client_code()
{
auto foo = Foo("Initial string");
// should now return **false** because
// the object has not yet been changed:
foo.is_changed();
foo.set_my_string("Changed string");
// should now return **true** because
// the object has been changed:
foo.is_changed();
}
(*)在实践中,不一定在理论上(如uuids在理论上不是唯一的)。
答案 0 :(得分:1)
您可以使用CRC32 algorithm from Boost。将其与要校验和的数据的内存位置一起提供。对于此示例,我已将另一个数据成员添加到Foo
:
int my_integer;
这就是你如何校验my_string
和my_integer
:
#include <boost/crc.hpp>
// ...
long current_fingerprint()
{
boost::crc_32_type crc32;
crc32.process_bytes(my_string.data(), my_string.length());
crc32.process_bytes(&my_integer, sizeof(my_integer));
return crc32.checksum();
}
您可以使用散列,但散列是用于防止故意数据损坏并且速度较慢的加密函数。 CRC表现更好。
答案 1 :(得分:0)
这样的功能不存在,至少在您请求的上下文中不存在。
STL为基本类型(std :: hash)提供哈希函数,您可以使用它们使用任何合理的哈希算法为对象实现哈希函数。
然而,你似乎在寻找一个导致问题的内射函数。基本上,要有一个内射函数,有必要输出大小或等于你正在考虑的对象的大小,因为否则(从鸽子孔原理)将有两个输出给出相同的输出。鉴于此,最明智的选择是将对象与某种参考对象进行直接比较。