C++ - 如何存储多维向量?

C++ - How are multi-dimensional vectors stored?

我有两个关于矢量的问题。

  1. 假设我有一个多维向量如下:-

    vector< vector<int> > A;

    A[0]A[1]等都是向量。 A 中的向量是如何存储的?我 A[0]A[1] 向量的什么信息存储在 A 中? 并重新分配单个向量的内存,例如 A[2] 也会导致 A 的重新分配?

  2. 其次,我试图查看向量的地址如何随着重新分配而变化。我使用了以下代码:-

代码:

vector<int> A;
int* x ;
int* y ;

vector<int>* ad;
vector<int>* bd;

for(int i = 0 ; i < 10000; i++){

    A.push_back(i);
    if(i == 2){
        y = &A[0];
        ad = &A;
    }
    x = &A[0];
    bd = &A;    

}

我发现,即使 A[0] 的地址发生变化,A 的地址也不会发生变化。这是意料之中的,因为矢量通过使用 newdelete 在后台工作。但我的问题是地址 &A 中存储了多少关于向量的信息(或哪些信息)(考虑到 &A 的地址不会改变)。这也是我对第一个问题的疑问。

我正在尝试更好地理解默认情况下向量的工作方式。

关于vector的地址A的地址没有变化,不是因为A是vector,而是因为没有[=29] =] 变量的地址在您定义它的函数(或者更确切地说,您的函数的特定调用)正在执行时发生变化。我认为您可能将 A 的地址(在您的示例中为 ad、bd)与 A 用于存储向量元素的地址(在您的示例中基本上是 x 和 y)混淆了。向量分配、取消分配或重新分配存储。

请注意,A[0] 不是您定义的变量。它是 A.operator[] 调用的结果;所以它的位置可以改变。

关于 &A 中实际存储的内容:这有点复杂。您需要查看 C++ 安装中的头文件 vector。或者看看 webpage for std::vector at cppreference.com 可能会更好。请注意,有很多模板,一些 subclassing,以及一些明确的模板特化,所以就像我说的 - 复杂。您可能需要重新考虑您是否 真的 想深入了解这个容器作为一般规则是如何工作的,或者 class' public 方法和 sizeof() 这个数字现在已经足够了。

how much information (or which information) about the vector is stored in the address &A

您假设向量的数据与向量对象本身分开存储是正确的 - 通常在动态内存中。

矢量对象本身需要知道的三件事是

  • 矢量数据的位置 - 我们需要它来执行 [] 运算符,
  • 当前分配的大小 - 我们需要它来知道何时增长数组,并且
  • 实际放入向量中的元素数量 - 我们需要它来知道 push_back 的位置以及从 [=13] 到 return 的内容=].

不同的实现是可能的,在矢量对象本身中存储尽可能少的单个指针。然而,一个典型的实现存储了一个指向分配块开始的指针,一个指向分配块活动部分末尾的指针,以及一个指向分配块末尾的指针。

我是c++和STL的初学者,所以我只是用一些简单的代码来测试你的问题; 首先,我有这些代码:

std::vector<int> tmp;
std::cout << sizeof(tmp) << " " << tmp.size() << " " << tmp.capacity << std::endl;

输出是:

12 0 0

然后,我们向向量中插入一些值

for(int i = 0; i != 10; ++i) tmp.push_back(i);
std::cout << sizeof(tmp) << " " << tmp.size() << " " << tmp.capacity << std::endl;

输出是

12 10 16

那么,我们可以得出结论,vector只是保留了一个指针,所以sizeof()的结果并没有改变。 所以,你的问题的答案是,子向量的push_back不会导致父向量的重新分配(我不知道如何表达这两个向量的作用)。 有一些简单的代码:

std::vector<int> v1(10);
std::vector<int> v2(10);

int i;
for(i = 0; i != 10; ++i)
    v1[i] = i;
for(i = 0; i != 10; ++i)
    v2[i] = i;

vv.push_back(v1);
vv.push_back(v2);

std::cout << "v1 capacity: " << v1.capacity() << "  v1 size: " << v1.size() << std::endl;
std::cout << "v2 capacity: " << v2.capacity() << "  v2 size: " << v2.size() << std::endl;
std::cout << "vv capacity: " << vv.capacity() << "  vv size: " << vv.size() << std::endl;

for(i = 10; i != 20; ++i)
    v1.push_back(i);
for(i = 10; i != 20; ++i)
    v2.push_back(i);

std::cout << "v1 capacity: " << v1.capacity() << "  v1 size: " << v1.size() << std::endl;
std::cout << "v2 capacity: " << v2.capacity() << "  v2 size: " << v2.size() << std::endl;
std::cout << "vv capacity: " << vv.capacity() << "  vv size: " << vv.size() << std::endl;

输出:

v1 capacity: 10  v1 size: 10
v2 capacity: 10  v2 size: 10
vv capacity: 2  vv size: 2
v1 capacity: 20  v1 size: 20
v2 capacity: 20  v2 size: 20
vv capacity: 2  vv size: 2