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

vector<int*>指向vector<int>元素出现未定义行为的原因排查

vector<int*>指向vector元素时的指针失效问题

我尝试创建一个vector<int*>,让它的元素指向vector<int>的元素(用于竞赛编程场景),但运行代码时出现异常:第一行输出的指针指向值不符合预期,不同编译器输出结果不同,期望两行输出内容一致。

原代码

#include <bits/stdc++.h>

using namespace std;

int ct = 0;

vector<int> vec;

vector<int*> rf;

void addRef(int n){
    vec.push_back(n);
    rf.push_back(&vec[ct]);
    ct++;
}

int main(){
    addRef(1);
    addRef(2);
    addRef(5);
    for(int i = 0; i < ct; i++){
        cout << *rf[i] << ' ';
    }
    cout << endl;
    for(int i = 0; i < ct; i++){
        cout << vec[i] << ' ';  
    }
}

运行结果

Dev-C++输出:

1579600 2 5
1 2 5

在线编译器输出:

1197743856 0 5 
1 2 5 

原因分析

核心问题是vector的自动扩容机制导致指针失效:

  • vector初始化时容量很小,当调用push_back且当前容量不足以容纳新元素时,会自动分配一块更大的内存空间,把原有元素全部拷贝到新内存,再释放旧内存。
  • 你在addRef中保存的是旧内存里元素的地址,旧内存被释放后,这些指针就变成了悬空指针,访问悬空指针属于C++未定义行为,所以不同编译器会输出不同的乱码值。

实现错误

在addRef函数中,每次vec.push_back(n)后直接取&vec[ct]的地址,但没考虑到push_back可能触发扩容,导致之前保存的指针指向的内存已被回收,后续访问必然出错。

修正方案

方案一:提前预留足够容量(最简单直接)

在main开头给vec预留足够容量,避免扩容操作,这样元素的地址就不会改变:

#include <bits/stdc++.h>
using namespace std;

int ct = 0;
vector<int> vec;
vector<int*> rf;

void addRef(int n){
    vec.push_back(n);
    rf.push_back(&vec[ct]);
    ct++;
}

int main(){
    vec.reserve(3); // 提前预留至少3个元素的容量,按需调整
    addRef(1);
    addRef(2);
    addRef(5);
    for(int i = 0; i < ct; i++){
        cout << *rf[i] << ' ';
    }
    cout << endl;
    for(int i = 0; i < ct; i++){
        cout << vec[i] << ' ';  
    }
}

方案二:用索引代替指针(竞赛推荐)

竞赛中更推荐直接保存元素的索引,vector的索引在不插入/删除中间元素的情况下是稳定的,完全可以替代指针,还能避免指针失效问题:

#include <bits/stdc++.h>
using namespace std;

int ct = 0;
vector<int> vec;
vector<int> rf; // 保存索引,而非指针

void addRef(int n){
    vec.push_back(n);
    rf.push_back(ct); // 保存当前元素的索引
    ct++;
}

int main(){
    addRef(1);
    addRef(2);
    addRef(5);
    for(int i = 0; i < ct; i++){
        cout << vec[rf[i]] << ' '; // 通过索引访问
    }
    cout << endl;
    for(int i = 0; i < ct; i++){
        cout << vec[i] << ' ';  
    }
}

方案三:使用不扩容的容器(按需选择)

如果一定要用指针,可以改用固定大小的array,或者用list(list的元素地址不会因插入改变,但随机访问效率低,竞赛中很少用)。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 13:45:44