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

为何std::vector内部对象的地址会发生变化?

关于std::vector对象地址变化的疑问

测试代码

// Example program
#include <iostream>
#include <string>
#include <vector>
struct Foo {
    int value = 0;
};

int main()
{
  std::vector<Foo> objs;
  for (int idx = 0; idx < 5; idx++) {
      objs.push_back(Foo{.value = idx});
      std::cout << "address: " << &(objs.back()) << "\n";
  }
  
  std::cout << "=======\n";
  for (const auto& obj: objs) {
      std::cout << "address: " << &(obj)<< "\n";
  }
}

问题描述

原本以为前后两次循环打印的对象地址应该完全一致,但实际运行后发现并非如此(第一次循环的地址会出现跳跃,第二次循环的地址是连续且稳定的)。该如何理解这种现象?是否是std::vector类在内部对对象进行了移动/重定位?


解答

这完全是std::vector的扩容机制导致的,核心原因在于它的底层实现是连续内存数组:

  • 当调用push_back添加元素时,如果当前vector的容量(capacity())不足以容纳新元素,会自动触发扩容:分配一块更大的新内存空间,把原内存里的所有对象拷贝/移动到新内存,然后释放旧内存。
  • 第一次循环中,每次push_back后立刻打印back()的地址,而每次扩容都会让之前的所有对象迁移到新地址,所以前几次打印的是旧内存地址,后续扩容后新元素的地址在新内存中,导致地址不连续;第二次循环是在所有元素添加完成后执行的,此时vector的容量已经足够,所有对象稳定存放在最终的连续内存块中,所以打印的地址连续且一致。
  • 可以在循环中加入std::cout << "capacity: " << objs.capacity() << "\n";,直观看到每次扩容时容量的变化,对应地址的跳转。
  • 如果想要避免这种地址变化,只需在添加元素前调用objs.reserve(5);预分配足够的容量,push_back过程中就不会触发扩容,前后两次打印的地址会完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 05:13:10