【问题标题】:C++ - How are multi-dimensional vectors stored?C++ - 如何存储多维向量?
【发布时间】:2015-12-17 05:51:50
【问题描述】:

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

  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 的地址并没有改变,即使A[0] 的地址发生了变化。这是意料之中的,因为向量通过使用newdelete 在后台工作。但我的问题是有多少关于向量的信息(或哪些信息)存储在地址&amp;A 中(考虑到&amp;A 的地址没有变化)。这也是我对第一个问题的疑问。

我试图更好地理解向量在默认情况下是如何工作的。

【问题讨论】:

  • 这很简单:std::vector&lt;X&gt; 包含X 对象,无论X 的类型如何(std::vector&lt;bool&gt; 可能例外。)
  • What is stored in A 类型为vector&lt;int&gt; 的元素,当然,看到A 的类型是vector&lt;vector&lt;int&gt;&gt;(而不是vector&lt;T*&gt; 对于某些类型T)。 I suspect that it stores the pointers你怀疑的依据是什么?
  • STL 与 c++ 标准库不同。
  • how much information ... is stored in the address &amp;A 当然,只有足够的信息来定位A 的内存表示。对于任何对象的地址都是如此。
  • 我根据您@Igor 的评论对原始问题进行了一些更改。

标签: c++ vector dynamic-memory-allocation


【解决方案1】:

关于向量的地址A的地址不会改变,不是因为A是向量,而是因为no变量的地址会随着你所在的函数而改变定义它(或者更确切地说,您的函数的特定调用)正在执行。我认为您可能会将 A 的地址(在您的示例中为 ad、bd)与 A 用于存储向量元素的地址(在您的示例中本质上是 x 和 y)混淆。向量分配、取消分配或重新分配存储。

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

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

【讨论】:

  • 是的,但是 A[0] 的地址改变了。即 A[0] 所在的位置发生了变化,我想那是因为重新分配。
  • 我想知道它是否将实际元素存储在 at &A 中,我现在不认为它会存储。我主要关心的是,如果在多维向量 A(问题 1)中,我将元素插入到向量 A[2] 中,A 中是否会有任何内存重新分配? (在A[2]中可以重新分配内存。但是A中的向量数量没有改变,所以我正在确认A中是否会重新分配)。
  • @Blastfurnace,我有这个担心是因为 .在我的应用程序中,我有 n 个一维向量,每个向量的大小都可能在运行时动态变化。但是数字 n 是固定的。所以我正在考虑使用二维向量。 (早些时候我很困惑是否应该存储指向 n 个 1-d 向量的指针,因为担心父向量中的重新分配,由于子向量中的重新分配)。
  • @ameyask86:我不会求助于原始指针。只要外部向量不增长(固定在n),那么内部向量就不会移动。每个“行”可能会重新分配它拥有的内存,但向量对象本身不会移动。
  • @Blastfurnace:是的,当然。我让 C 编程占据了我的大脑一秒钟(即a[b] *(a + b),这在 C++ 中是不正确的)。
【解决方案2】:

在地址&amp;A中存储了多少关于向量的信息(或哪些信息)

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

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

  • 向量数据的位置 - 我们需要它来执行[] 运算符,
  • 当前分配的大小 - 我们需要它来知道何时增加数组,并且
  • 实际放入向量中的元素数量 - 我们需要它来知道push_back 的位置,以及从size() 返回的内容。

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

【讨论】:

  • 所以,如果我有一个 int 向量的向量,比如 A (in question 1),如果我将元素添加到一维向量中,它的内存将不会被重新分配。但是如果我向 A 添加一个新的一维向量,它的内存可能需要重新分配。我有这些问题是因为这种存储方法与多维数组相比有很大不同。 (我经常使用数组,但没有使用向量)
  • @ameyask86 你是对的,添加到内部向量不会导致重新分配外部向量。二维数组与向量的向量的存储模型非常不同。在某些情况下,这变得很重要 - 例如,当您优化 CPU 缓存访问策略时:具有长而窄的 2D 数组的程序可以比具有相同大小向量的程序获得更好的性能。
【解决方案3】:

我是 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

【讨论】:

    猜你喜欢
    • 2017-10-03
    • 1970-01-01
    • 1970-01-01
    • 2020-12-01
    • 2013-03-07
    • 2014-08-10
    • 2013-08-03
    • 2017-05-10
    • 2012-11-14
    相关资源
    最近更新 更多