在向向量

时间:2016-09-07 05:35:41

标签: c++ vector stl

考虑以下代码:

int main()
{

    std::vector<std::string> v;

    v.push_back("hello");
    v.push_back("stack");

    std::string &s = v[0];

    v.push_back("overflow");

    std::cout << s << std::endl;

    return 0;
}

运行后(使用g++ (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4),只打印一个空行,不打印hello。如果我注释掉v.push_back("stack");,则会出现细分错误。

现在我明白为什么会这样。向向量添加更多元素会触发引擎下的增长操作,之后我的旧引用变为无效。这不是我的问题。

我的问题是这种行为 - 在获取引用/指针后修改向量或其他STL容器 - 是否被定义为C ++标准中的未定义行为?如果是的话,在哪里?如果没有那么标准对这种情况说了什么?

2 个答案:

答案 0 :(得分:3)

C ++ 14 [vector.capacity] / 6:

  

重新分配使引用序列中元素的所有引用,指针和迭代器无效。

[vector.modifiers] / 6涵盖了push_back可能导致重新分配的问题,只有在迭代器没有重新分配时才会失效。

我实际上找不到任何文本来定义引用无效的含义,但很明显暗示在无效之后使用引用的值将是未定义的行为。

答案 1 :(得分:2)

仅仅因为您通过某种方式获取了迭代器,引用或指针,因此不会禁止修改容器。 可能无效的是迭代器,引用或指针本身。

§23.3.6.6[vector.modifiers] (包括push_back成员系列)

  
      
  1. 备注:如果新大小大于旧容量,则会导致重新分配。如果没有重新分配,则之前的所有迭代器和引用   插入点仍然有效。如果抛出异常而不是   通过复制构造函数,移动构造函数,赋值运算符或   移动T的赋值运算符或任何InputIterator操作   没有影响。如果插入单个时抛出异常   最后的元素和T是CopyInsertable或   is_nothrow_move_constructible<T>::value是真的,没有效果。   否则,如果a的移动构造函数抛出异常   非CopyInsertable T,效果未指定。
  2.   

如果没有发生调整大小,则只有插入点之后的引用,指针和迭代器(包括结束迭代器)无效。很好,但如果重新分配发生会发生什么?有趣的是,我们发现:

§23.3.6.3[vector.capacity]

  
      
  1. 备注:重新分配使所有引用,指针和   迭代器引用序列中的元素。没有重新分配   应在呼叫后发生的插入过程中发生   reserve()直到插入的大小为止   vector大于capacity()的值。
  2.   
但是,我并不完全相信这完全回答了你的问题。如果你想知道占用矢量的先前内存发生了什么,那就是标准库,但它不再包含可行的内容。容器不再拥有内存(据你所知),你也不知道。