You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

std::map插入对象时构造函数内变量地址异常问题咨询

拆解你的C++代码问题:拷贝构造引发的悬空指针陷阱

嘿,咱们一步步来理清楚你遇到的问题:

为什么第一个代码里地址不一样,还出现垃圾值?

当你执行map.insert(std::make_pair(4, exampleClass{}));的时候,背后发生了这些事:

  1. 你先创建了一个临时的exampleClass对象(就是exampleClass{}),这个对象住在栈内存里,也就是构造函数打印的0x7ffee080b500地址。这个临时对象的innerMap里存了指向自己成员a的指针。
  2. 接着std::make_pair会把这个临时对象完整拷贝一份,做成pair的第二个元素;然后map.insert又把这个pair拷贝到map自己管理的内存里(通常是堆内存,也就是你循环里看到的0x559ddb2c42e8地址)。
  3. 临时对象完成拷贝任务后,会立刻被销毁——但你之前存在innerMap里的指针,还死死指着那个已经被销毁的临时对象的a的地址!这就成了悬空指针,当你最后一行解引用这个指针时,那块内存已经被系统回收或者被其他数据覆盖了,自然会输出莫名其妙的垃圾值(比如6.95312e-310)。

至于构造函数和循环里的地址不一样?那是因为循环里的对象是临时对象的拷贝副本,它和原临时对象是完全独立的两个实例,一个在堆里,一个在栈里,地址当然不同啦。

为什么第二个代码能正常运行?

你直接写exampleClass abc{};的时候,这个abc是一个在栈上持久存在的对象,它的生命周期覆盖了后面所有的打印操作——从创建到你打印完,abc一直活着,所以innerMap里的指针始终指向有效的内存(abc.a的地址),解引用自然能得到正确的12.1。

怎么解决第一个代码的问题?

给你几个实用的方案:

  • 方案一:直接在map里构造对象,避免拷贝
    用emplace配合piecewise_construct,让exampleClass直接在map的内存里构造,完全跳过临时对象的环节:
    map.emplace(std::piecewise_construct,
                std::forward_as_tuple(4),
                std::forward_as_tuple());
    
    这样构造出来的对象,innerMap里的指针指向的就是自己的a,不会有悬空问题。
  • 方案二:不要存指针,直接存值
    如果业务逻辑允许,把innerMap的类型改成std::map<int, double>,直接存a的值而不是指针,从根源上避免指针悬空的风险。
  • 方案三:自定义拷贝构造函数,修正指针指向
    当对象被拷贝时,手动更新innerMap里的指针,让它指向新对象的a:
    struct exampleClass {
        double a = 12.1;
        std::map<int, double*> innerMap;
        exampleClass() {
            std::cout << "ADR of variable a in constructor = " << &a << std::endl;
            std::cout << "ADR of this in constructor = " << this << std::endl;
            innerMap.emplace(4,&a);
        }
        // 自定义拷贝构造函数
        exampleClass(const exampleClass& other) : a(other.a), innerMap(other.innerMap) {
            // 将innerMap中的指针替换为当前对象的a的地址
            innerMap[4] = &a;
        }
    };
    
    这样拷贝出来的对象,innerMap里的指针就指向自己的a了,不会再悬空。

内容的提问来源于stack exchange,提问作者Peter Lustig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:08:52