使用(void *)作为标识符的类型

时间:2009-12-08 08:59:02

标签: c++ identity strict-aliasing

在我的程序中,我有对象(同一类)必须都有唯一标识符。为了简单和性能,我选择使用对象的地址作为标识符。为了简化类型,我使用(void*)作为此标识符的类型。最后我有这样的代码:

class MyClass {
public:
  typedef void* identity_t;
  identity_t id() const { return (void*)this; }
}

这似乎工作正常,但gcc给了我一个严格别名的警告。我知道如果id用于数据传输,代码会很糟糕。幸运的是它不是,但问题仍然存在:别名优化是否会对生成的代码产生影响?以及如何避免警告?

注意:我不愿意使用(char*),因为这意味着用户可以使用数据进行复制,但它无法使用!

5 个答案:

答案 0 :(得分:4)

您可以尝试使用uintptr_t类型代替void*uintptr_t是一个整数类型,定义为足以容纳任何指针值。由于它实际上不是指针,编译器不会标记任何别名问题。

class MyClass {
public:
    typedef uintptr_t identity_t;
    identity_t id() const { return (identity_t)this; }
}

答案 1 :(得分:3)

你违反了逻辑constness,在const方法中将对象返回为可变对象 正如尼尔指出的那样,不需要演员表。

class MyClass {
public:
  typedef const void* identity_t;
  identity_t id() const { return this; }
};

答案 2 :(得分:2)

尝试使用

return static_cast<void*>(this);

这应该是完全安全的,任何指针都应该能够转换为void *而不会有丢失的风险。

我最初建议使用dynamic_cast(this);,但在阅读之后我认为它没有任何优势,因为它只是RTTI,所以它通常不是一个好的解决方案。

顺便说一句,我会返回值const,因为对象的身份不能改变。

答案 3 :(得分:1)

我看不到任何别名问题。但是,您正在抛弃constness(因为id函数是const),编译器可能对此不满意。也许最好使用const void*作为您的ID类型。

或者,将地址转换为整数类型,例如size_t。然后它不再是一个指针,并且别名变成一个非问题。

答案 4 :(得分:0)

为什么不使用MyClass *类型?

或输入intptr_t