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

为何C++中两个vector输出结果异常?指针vector出现垃圾值

问题分析:vector扩容导致悬空指针引发垃圾值输出

结构体定义

struct C
{
  int i;
};

主程序代码

std::vector<C*> vc;
std::vector<C> vcc;

int main()
{
    for (int i = 0; i < 10; ++i)
    {     
        C c;
        c.i = i;
        vcc.emplace_back(c);
        vc.emplace_back(&vcc[i]);       
    }

    for (int i = 0; i < 10; ++i)
    {
        std::cout << vc[i]->i << " "; // 预期输出0,1,2,...,9但出现垃圾值
    }
}

实际输出

0,-572662307,-572662307,3,-572662307,-572662307,-572662307,-572662307,-572662307,9


原因解析

问题核心在于std::vector的扩容机制:

  • 当调用vcc.emplace_back(c)添加元素时,如果当前容器剩余容量不足,它会重新分配一块更大的内存,把旧内存里的元素全部拷贝过去,然后释放旧内存。
  • 你在每次添加元素后,把&vcc[i](当前元素在vcc中的地址)存入vc。一旦vcc触发扩容,之前存在vc里的指针就变成了悬空指针——它们指向的旧内存已经被系统回收,再通过这些指针访问数据,得到的就是未定义的垃圾值。
  • 个别正确值的出现是因为vector扩容并非每次添加元素都会触发,比如初始容量可能是1、2、4、8...,当添加第1、4、10个元素时,刚好没触发扩容,对应的指针还指向有效内存,所以能输出正确值;其他时候因扩容导致指针失效,就输出垃圾值。

解决方案

方案一:提前预留容量避免扩容

在main开头给vcc预留足够存储空间,确保整个循环过程中不会触发扩容,所有指针始终指向有效内存:

struct C
{
  int i;
};

std::vector<C*> vc;
std::vector<C> vcc;

int main()
{
    vcc.reserve(10); // 提前分配能容纳10个元素的内存
    for (int i = 0; i < 10; ++i)
    {     
        C c;
        c.i = i;
        vcc.emplace_back(c);
        vc.emplace_back(&vcc[i]);       
    }

    for (int i = 0; i < 10; ++i)
    {
        std::cout << vc[i]->i << " "; // 正确输出0 1 2 ... 9
    }
}

方案二:避免存储裸指针(更推荐)

如果不需要单独存储指针,直接遍历vcc输出即可;若必须存储指针,建议用智能指针(如std::unique_ptr<C>)管理内存,从根源上避免悬空指针问题:

#include <memory>

struct C
{
  int i;
};

std::vector<std::unique_ptr<C>> vc;

int main()
{
    for (int i = 0; i < 10; ++i)
    {     
        auto c = std::make_unique<C>();
        c->i = i;
        vc.emplace_back(std::move(c));       
    }

    for (int i = 0; i < 10; ++i)
    {
        std::cout << vc[i]->i << " "; // 正确输出0 1 2 ... 9
    }
}

内容的提问来源于stack exchange,提问作者green cross

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 14:45:30