首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >骚操作之内存地址做唯一标识符

骚操作之内存地址做唯一标识符

作者头像
程序员的园
发布2025-05-12 20:43:13
发布2025-05-12 20:43:13
13200
代码可运行
举报
运行总次数:0
代码可运行

这篇文章真的是我最近最想写的一篇文章,倒不是本文所述的知识点有多高级,而是因为这个知识点比较讨巧——太骚了,哈哈哈。且听我慢慢道来。

1. 前言

当一个系统内存在很多个对象且希望能够操作任意指定的对象时,对象需要提供一个唯一标识符,可以是独一无二的名字,也可以是GUID,但是:

  • 名字可能会重复:名字是绝对有可能会重复的。如果为了保证名字的唯一性,每次新生成对象的名字均需要对已存在的名字进行判断,如果存在则需要取新名字,这样效率太低,且容易出错。
  • GUID太长:GUID可以保证名字的唯一性,但是128位的GUID相对来讲有些长,存储时会增加内存占用,传输时会增加带宽占用,打印输出时也不方便(通常转换为字符串输出)

虽然GUID太长,但是我们仍旧可以借用其思路来选择一个数字作为唯一标识符。

2. 内存地址

在C++中,每个对象在内存中都有一个地址,可以认为存在如下的流程:

  • 构建对象后,系统会为对象分配内存空间,并返回一个地址,由于该地址对应一个具体的内存空间,所以在该进程内的当前时刻,该地址是唯一的。
  • 对象存续期间,即使会为构建其他对象,但是该对象的地址空间也不会发生变化,所以该地址仍旧是唯一的。
  • 对象被析构后,该地址空间会被回收,可能会在该地址上构建新的对象,但是当对象被析构时,该对象已经不存在了,所以也就不需要唯一标识符来表征它。 综上我们可以使用内存地址作为对象存续期间的唯一标识符

3. 实现方案

在32位软件中,对象的内存地址为32位4个字节,在64位软件中,对象的内存地址为64位8个字节,所以如果代码要同时支持32位和64位,则应该是使用64位来存储内存地址。毕竟64位可以存储32位、64位的内存地址,但是32位不能存储64位的内存地址。 所以该唯一标识符应该使用uint64_t类型来存储。具体的使用方式如下:

代码语言:javascript
代码运行次数:0
运行
复制
#include <iostream>


class Test{
public:
    Test(){
        m_id = reinterpret_cast<uint64_t>(this);
    }

    ~Test(){
        m_id = 0;
    }

    uint64_t GetId() const{
        return m_id;
    }

private:
    uint64_t m_id;
};

int main(){
    Test t1;
    Test t2;
    std::cout << "t1 id: " << t1.GetId() << std::endl;
    std::cout << "t2 id: " << t2.GetId() << std::endl;

    auto  new_t1 = new Test();
    auto  new_t2 = new Test();
    std::cout << "new_t1 id: " << new_t1->GetId() << std::endl;
    std::cout << "new_t2 id: " << new_t2->GetId() << std::endl;

    return 0;
}
//x64输出:
// t1 id: 368160273736
// t2 id: 368160273768
// new_t1 id: 2076629290624
// new_t2 id: 2076629291104

//x86输出:
// t1 id: 9435020
// t2 id: 9435004
// new_t1 id: 13305544
// new_t2 id: 13306664

经过测试,x64和x86下均可以正常使用,且内存地址是唯一的,所以该方案是可行的。

4. 优势

使用内存地址转为uint64_t作为唯一标识符,有如下优势:

  • 唯一性:对象存续期间内存地址是唯一的,所以该标识符也是唯一的,永远不会出现冲突。
  • 长度适中:64位可以存储32位、64位的内存地址,所以该标识符长度适中。同时较GUID的128位,该标识符的长度只有其一半。
  • 架构无关:无论输出x86还是x64程序,均可以正常标识,且不会出错。

但是这种方法也存在其限制,对象存续期间该标识符是唯一的,当对象被析构后,地址可能会被重用,从而导致地址并不是唯一的,进而影响唯一性。

5. 总结

本文介绍了使用内存地址作为唯一标识符的骚操作,该操作具有唯一性、长度适中、架构无关等优势,是一个值得推荐的操作。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-05-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员的园 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 前言
  • 2. 内存地址
  • 3. 实现方案
  • 4. 优势
  • 5. 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档