【问题标题】:One question about vector push_back关于vector push_back的一个问题
【发布时间】:2015-12-26 23:29:33
【问题描述】:

我刚刚注意到,对于向量 push_back,它是推回对元素的引用。

void push_back ( const T& x );

我的问题是 push_back 后内存布局有变化吗?

例如,我首先有一个包含五个元素的数组,布局是这样的。

|          |          |          |          |          |              
|   A1     |     A2   |   A3     |    A4    |    A5    |

现在我有一个向量 v

v.push_back(A3)

现在,内存是什么样子的?

vector是如何把元素存储在这里的?

vector如何访问元素?

【问题讨论】:

  • 看看 vector::reserve 和 vector::capacity 的内存布局。请记住,由于内存分配可能会发生变化,一旦您修改了向量的内容,您在 push_back 调用之前拥有的任何迭代器都会失效。

标签: c++ vector


【解决方案1】:

向量按值而非引用存储

当您重新添加相同的元素时,将在最后存储一个副本。如果您不想复制要插入到 vector 中的值,则应使用指针。

例子:

std::vector<std::string> v;
string s = "";
v.push_back(s);
s = "hi";
v.push_back(s);

v 现在包含 2 个不同的元素,一个是空字符串,一个是包含 "hi" 的字符串。向量中的两个字符串都独立于s

注意:STL 容器的内部实现细节可能会有所不同,不能保证一定会以某种方式实现;但是,无论内部实现是什么,STL 容器如何工作的语义都将保持不变。

【讨论】:

  • std::vector 的语义确实包括内存格式,从 2003 年“TC1”开始,它必须位于连续内存中。无论如何,所有的实现都是这样做的。
【解决方案2】:

现在,内存是什么样子的?向量如何将元素存储在这里?

有两种可能的结果:

  1. 向量的内存块不足以容纳项目,因此重新分配了底层内存。对象被复制(使用它们的复制构造函数)到它们的新位置。然后将push_back'd 对象(按值)复制到末尾。
  2. 向量的内存块足够大,新元素被复制(按值)到末尾。

向量如何访问元素?

访问 C 样式数组的方式相同。 BasePointer + index

【讨论】:

    【解决方案3】:

    vector::push_back 接受一个引用,然后读取引用处的值以将其复制到向量中。

    所以结果向量是

    | A3 |
    

    请注意,当调整向量的大小以适应新数据时,它可能会将旧数据移动到新位置,从而使旧引用无效。所以如果列表 A1, A2, ... A5 v,

    v.push_back(A3)
    

    将使A3 无效,因为A3 引用v 中的数据。在向量增长时保持对数据句柄的唯一方法是保存索引;引用、指针和迭代器不行。

    【讨论】:

    • 不,它不会使 A3 无效,因为它是按值完成的。结果向量将是 | A3 | A3 |在你的例子中。两个对象仍然有效。
    • @Billy:我假设 A3 是对v 内部对象的引用。仔细阅读。
    • 不,OP 说 push_back 需要一个参考参数,但就是这样。
    • @Billy:这就是我使用if这个词的原因:“所以如果列表 A1、A2、... A5 是 v,”
    【解决方案4】:
    |   A1     |     A2   |   A3     |    A4    |    A5    |   A3     |
    

    元素(就像 STL 中的所有内容一样)按值存储。

    向量访问元素就像内置数组一样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-15
      • 2016-03-31
      • 2022-09-30
      相关资源
      最近更新 更多