为何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
相关产品推荐
相关产品推荐

