C++ 向量重排序的保证

C++ 向量重排序的保证,c++,vector,language-lawyer,C++,Vector,Language Lawyer,假设我有这个代码: #include <iostream> #include <vector> int main() { std::vector<int> vec {10, 15, 20}; auto itr = vec.begin(); vec.erase(itr); for(const auto& element : vec) { std::cout << element &l

假设我有这个代码:

#include <iostream>
#include <vector>

int main() 
{
    std::vector<int> vec {10, 15, 20};
    auto itr = vec.begin();
    vec.erase(itr);
    for(const auto& element : vec)
    {
        std::cout << element << " ";
    }
    return 0;
}
或者,是否允许实现在其认为合适的情况下移动值,从而创建
vec[0]==20的场景


我想引用标准的相关部分。

让我们从开头开始:

23.2.3序列容器

序列容器将所有类型相同的有限组对象组织成严格的线性排列。 该库提供了四种基本类型的序列容器:向量, 转发列表、列表和数据

强调“严格的线性排列”。这是明确的

该定义后面是一个名为“序列容器要求”的表,该表描述了
erase()
因此:


加在一起,这就没有留下任何解释的余地。向量中的元素始终处于“严格的线性排列”,因此当其中一个元素是
erase()
d时,只有一种可能的结果。

从技术上讲,不,标准没有承诺不会在您最不期望的时候重新排序元素

实际上,很明显它不会那样做。那太荒谬了

从法律上讲,您可能可以使用“效力”条款:

删除由q指向的元素


除非另有说明,否则没有其他影响(例如,迭代器失效,由擦除效应产生)。

我发现的两个声明可以保证:

C++11标准

23.2.1 11除非另有规定(明确地或通过根据其他函数定义函数),调用容器成员函数或将容器作为参数传递给库函数不得使迭代器失效或更改容器内对象的值

如果您不能“更改”元素的值,那么您就不能任意地重新排序元素(比如用已擦除的元素交换结束值)

23.2.3 12从a.erase(q)返回的迭代器指向被擦除元素之前紧跟在q之后的元素。如果不存在这样的元素,则返回a.end()

这意味着元素的概念擦除是通过闭合右侧的物理间隙来实现的。鉴于前面的规则,从概念上缩小差距不能被视为从概念上改变其值。这意味着唯一的实现将是按顺序移动值

通过解释的方式。

该标准处理的是抽象概念,而不是实际的实现,尽管其声明确实会影响实现

从概念上讲,删除一个元素只会删除它,仅此而已。因此,根据顺序:

3  5  7  4  2  9 (6 values)
如果我们删除第三个元素,从概念上讲,这会给我们带来什么

这必须是正确的,因为上面的第一句话:

23.2.1 11除非另有规定(明确地或通过根据其他函数定义函数),调用容器成员函数或将容器作为参数传递给库函数不得使迭代器失效或更改容器内对象的值

如果实现对元素进行了重新排序,例如,通过将已擦除的元素与结束元素交换,则该规则将被打破,因为我们将以以下方式结束:

3  5  9  4  2  

从概念上讲,被擦除元素右侧的结果值已从4变为9,因此违反了规则。

在复杂性下,它说:“T的赋值运算符被称为等于被擦除元素之后向量中元素数的次数。”-这不意味着它必须按顺序复制以下所有元素吗?由于在erase()之后不使用迭代器,我不确定您在问什么。只有迭代器无效。@NeilButterworth这与迭代器无关,它与擦除后向量的状态有关。我还刚刚阅读了标准,对于无序关联容器,有一个条件是元素的相对顺序保持不变。不过,我找不到类似的序列声明。我相当肯定,该标准也不能保证您的计算机在调用
erase
后不会爆炸,但在某些情况下,您必须阅读字里行间的内容……嗯,一些摇摆空间-“严格线性”是什么意思,标准的其他地方有没有规定:-)我宁愿说“按照特定插入操作的顺序排序”,或者类似的话。Sam的答案更好,但我认为仍然有观察的余地,标准没有明确表示严格的线性排列没有“重新线性化”。但我在这里扮演魔鬼代言人的角色很大程度上是为了好玩。“标准并没有承诺在你最不经意的时候不会重新排序元素”——我认为它应该这么做。我想我们只是还没有找到它在哪里明确地表达了这一点。如果不这样做,那么这是标准中的一个bug。这样的事情确实存在,依赖于“明显的”不是一个好主意。@NeilButterworth:我同意这可能被视为编辑缺陷,尽管我怀疑我们是否会得到任何支持。当然不是从这里开始,但标准委员会的一些人可能会想一想“严格线性”应该是什么意思,甚至是什么意思(震惊,恐惧)定义它。也许发布一个关于它的SO问题可能会提高它的可见性?不,我不会这么做。@NeilButterworth:我的意思是,我怀疑工作组会在意。如果你不能“更改”的值,那么你就不能随意地重新排序元素(比如用删除的值替换结束值)。为什么不呢?元素的值不会改变,只是顺序改变了。这意味着元素的概念擦除是不正确的
3  5  7  4  2  9 (6 values)
3  5  4  2  9 (5 values)
3  5  9  4  2