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,它类似于一个向量,但地址永远不会改变。