静态变量的地址

Jur*_*aho 12 c++

我想尝试一个简单的类来进行唯一的ID转换.我正在考虑添加一个静态方法:

class A {
  static int const *GetId() {
    static int const id;
    return &id;
  }
};
Run Code Online (Sandbox Code Playgroud)

然后每个类将通过唯一标识int const *.这保证有效吗?返回的指针真的是唯一的吗?有没有更简单的解决方案?

我也想过指向std::type_info:

class A {
  static std::type_info const *GetId() {
    return &typeid(A);
  }
};
Run Code Online (Sandbox Code Playgroud)

那个更好吗?

编辑:

我不需要使用id进行序列化.我只想识别一小组基类,并希望某些类的所有子类具有相同的id

sha*_*oth 10

是的,这会奏效.static在加载模块时,每个本地将被赋予不同的内存位置,并且它将一直存在,直到模块被卸载.请记住,static本地存储在静态存储中,该存储在编译期间分发,并且一直存在直到模块被卸载,因此它们将具有不同的存储位置.


Che*_*Alf 7

静态变量的地址保证是唯一的,并且在所有翻译单元中都是相同的.

这不是一个好主意,因为它要求您为每个要识别的类添加代码.

类型信息对象的指针不保证是唯一的,但类型信息对象本身保证比较给定的类相等,不同的类不相等.这意味着您可以使用带有类型信息指针的小包装器对象,并委托对类型信息对象进行比较.C++ 11在标准库中有这样的包装器,如果你没有访问权限,那么Andrei Alexandrescu的"现代C++设计"就有一个,因此也许在Loki库中,可能有一个在Boost,我的Wordpress博客上有一个 - 它不像你从头开始发明一个.

但是,如果要将id用于序列化,则需要在构建版本之间有效的id.在这种情况下,您需要字符串或UUID.我会选择UUID.

要将类与UUID相关联,通常可以使用类型特征类.或者,如果您只是进行Windows编程,那么您可以使用Visual C++的语言扩展.我想但我并不是100%确定那些语言扩展也是由g ++实现的(在Windows中).

干杯和hth.


Jur*_*aho 3

正如我所注意到的,至少 MSVC 2008 或 2010 优化了静态变量,以便以下GetId函数即使对于不同的类也返回相同的地址。

static int const *GetId() {
    static const int i = 0;
    return &i;
}
Run Code Online (Sandbox Code Playgroud)

因此,未初始化的常量静态变量的地址不能用于标识。最简单的修复方法就是删除const

static int *GetId() {
    static int i;
    return &i;
}
Run Code Online (Sandbox Code Playgroud)

另一种生成 ID 的解决方案(似乎可行)是使用全局函数作为计数器:

int Counter() {
    static int i = 0;
    return i++;
}
Run Code Online (Sandbox Code Playgroud)

然后在需要识别的类中定义如下方法:

static int GetId() {
    static const int i = Counter();
    return i;
}
Run Code Online (Sandbox Code Playgroud)

由于要定义的方法始终相同,因此可以将其放入基类中:

template<typename Derived>
struct Identified {
    static int GetId() {
        static const int i = Counter();
        return i;
    }
};
Run Code Online (Sandbox Code Playgroud)

然后使用一种奇怪的重复模式:

class A: public Identified<A> {
    // ...
};
Run Code Online (Sandbox Code Playgroud)