C++ 填充std::vector时使用不同的地址

C++ 填充std::vector时使用不同的地址,c++,vector,initialization,stdvector,memory-address,C++,Vector,Initialization,Stdvector,Memory Address,难道你不认为这两个循环打印的地址是一样的吗?我是,我不明白为什么(有时)他们是不同的 #include <iostream> #include <vector> using namespace std; struct S { void print_address() { cout << this << endl; } }; int main(int argc,char *argv[]) { vector<S> v

难道你不认为这两个循环打印的地址是一样的吗?我是,我不明白为什么(有时)他们是不同的

#include <iostream>
#include <vector>
using namespace std;

struct S {
  void print_address() {
    cout << this << endl;
  }
};

int main(int argc,char *argv[]) {
  vector<S> v;
  for (size_t i = 0; i < 10; i++) {
    v.push_back( S() );
    v.back().print_address();
  }
  cout << endl;
  for (size_t i = 0; i < v.size(); i++) {
    v[i].print_address();
  } 
  return 0;
}

我发现了这一点,因为在第一个循环中进行了一些初始化,我在程序的后续部分获得了未初始化的对象。我遗漏了什么吗?

因为当向量容量改变时,它会重新分配元素。如果您有足够的容量,不需要重新配置,它将打印相同的地址

vector<S> v;
v.reserve(10);
向量v; v、 储备(10);
注意:正确使用将提高应用程序性能,因为没有不必要的重新分配和对象复制。

因为当向量容量改变时,它会重新分配元素。如果您有足够的容量,不需要重新配置,它将打印相同的地址

vector<S> v;
v.reserve(10);
向量v; v、 储备(10);
注意:正确使用将提高应用程序性能,因为没有不必要的重新分配和对象复制。

向量正在执行重新分配,以便根据需要增长。每次这样做时,它都会为数据分配一个更大的缓冲区,并跨多个服务器复制元素。您可以在第一个循环中清楚地看到这一点,每个地址跳转后面都有一个更大的连续地址序列。在第二个循环中,您只需查看最终重新分配后的地址

0xaec010
0xaec031  <--
0xaec012  <--
0xaec013
0xaec034  <--
0xaec035
0xaec036
0xaec037
0xaec018  <--
0xaec019

这将不涉及重新分配。另请参见。

向量正在执行重新分配,以便根据需要增长。每次这样做时,它都会为数据分配一个更大的缓冲区,并跨多个服务器复制元素。您可以在第一个循环中清楚地看到这一点,每个地址跳转后面都有一个更大的连续地址序列。在第二个循环中,您只需查看最终重新分配后的地址

0xaec010
0xaec031  <--
0xaec012  <--
0xaec013
0xaec034  <--
0xaec035
0xaec036
0xaec037
0xaec018  <--
0xaec019

这将不涉及重新分配。另请参见。

矢量元素连续存储;也就是说,它们都在内存中的一行中。向量对象必须为这个连续的元素块分配空间

你的向量不能无限期地添加东西。它必须扩大分配的空间。内存模型通常不允许我们扩展内存块——我们必须创建一个新的内存块。当向量执行此操作时,它必须将其所有元素移动到新空间。这在您的第一个循环中发生了几次

如果你做到了:

vector<S> v;
v.reserve(10);
向量v; v、 储备(10);
(你可以这样做,因为你知道最终会有10个元素),那么就不需要重新分配,地址也不会改变。

矢量元素是连续存储的;也就是说,它们都在内存中的一行中。向量对象必须为这个连续的元素块分配空间

你的向量不能无限期地添加东西。它必须扩大分配的空间。内存模型通常不允许我们扩展内存块——我们必须创建一个新的内存块。当向量执行此操作时,它必须将其所有元素移动到新空间。这在您的第一个循环中发生了几次

如果你做到了:

vector<S> v;
v.reserve(10);
向量v; v、 储备(10);
(你可以这样做,因为你知道你最终会有10个元素),那么就不需要重新分配,地址也不会改变。

我对它们会改变并不感到惊讶。由于向量最初没有大小,因此在初始循环中可能会重新分配向量一次或两次。这将更改向量的基址。调整大小后,您最终会使用以前使用的地址并非不可能(尽管我觉得这有点令人惊讶。您确定地址的第一部分吗?)


如果你想确保它们不会改变,你需要先添加一个
v.reserve()
,然后再开始在上面添加内容。

它们会改变,我并不感到惊讶。由于向量最初没有大小,因此在初始循环中可能会重新分配向量一次或两次。这将更改向量的基址。调整大小后,您最终会使用以前使用的地址并非不可能(尽管我觉得这有点令人惊讶。您确定地址的第一部分吗?)


如果你想确保它们不会改变,你需要先添加一个
v.reserve()
,然后再开始推它。

我真傻!这太清楚了!我只是被偶尔有相同的地址弄糊涂了,而所有的地址都被来回移动了不同的时间(除了最后两次)。大多数答案都是相同的。。。但我喜欢这个:)傻我!这太清楚了!我只是被偶尔有相同的地址弄糊涂了,而所有的地址都被来回移动了不同的时间(除了最后两次)。大多数答案都是相同的。。。但是我喜欢这个:)你可以尝试std::deque,它类似于一个向量,但地址永远不会改变。你可以尝试std::deque,它类似于一个向量,但地址永远不会改变。