向std::vector<std::reference_wrapper<int>>push_back后出现垃圾值,求原因及解决方法
问题分析与解决方案
这是个非常典型的std::vector内存重分配导致悬空引用的问题,我来给你拆解清楚:
为什么会出现垃圾值?
当你对v_i调用push_back时,vector会在内部存储空间不足的情况下,触发内存重新分配:它会申请一块更大的内存区域,把原有的所有元素拷贝/移动过去,然后释放原来的旧内存。
你在循环里每次push_back(i)后,立刻取v_i[i]的引用存到s_i里,但后续的push_back可能会让整个v_i的内存地址发生变化——包括你刚存入的第i个元素的地址!等循环结束后,s_i里保存的引用早就指向了被释放的旧内存,自然输出的就是随机垃圾值。
正确的添加方式
有几种可靠的解决办法,根据你的需求选择:
1. 提前预留足够空间(最简单直接)
在循环开始前,给v_i调用reserve()方法,提前分配好足够容纳10个元素的内存。这样后续的push_back不会触发内存重分配,所有元素的地址都会保持稳定:
#include <iostream> #include <vector> #include <functional> int main() { std::vector<int> v_i; v_i.reserve(10); // 提前预留10个元素的空间,避免重分配 std::vector<std::reference_wrapper<int>> s_i; for(int i=0;i<10;++i) { v_i.push_back(i); s_i.push_back(std::ref(v_i[i])); } std::cout<<v_i[0]<<std::endl; std::cout<<s_i[0].get()<<std::endl; return 0; // 建议返回0表示程序正常退出 }
2. 先填充完原vector,再创建引用
等v_i的所有元素都添加完毕、内存位置完全稳定后,再遍历它创建引用存入s_i:
#include <iostream> #include <vector> #include <functional> int main() { std::vector<int> v_i; // 先把所有元素加入v_i for(int i=0;i<10;++i) { v_i.push_back(i); } // 再批量创建引用 std::vector<std::reference_wrapper<int>> s_i; for(auto& num : v_i) { s_i.push_back(std::ref(num)); } std::cout<<v_i[0]<<std::endl; std::cout<<s_i[0].get()<<std::endl; return 0; }
3. 使用不会移动元素的容器(如果需要动态添加)
如果你需要频繁动态添加元素,且不想手动管理预留空间,可以换成std::list这类链表容器——它的元素不会因为添加新元素而移动位置,引用会一直有效。不过注意std::list没有随机访问能力,性能和使用场景和vector不同。
额外提醒
std::reference_wrapper本质就是对指针的包装,它不会延长所引用对象的生命周期,也无法感知对象地址的变化。所以使用它时,一定要确保被引用的对象生命周期足够长,且在持有引用期间不会被移动或销毁。
内容的提问来源于stack exchange,提问作者Ash
相关产品推荐
相关产品推荐

