std :: partition实现

问题描述

我已经阅读了std :: partition和std :: stable_partition之间的区别。 我也看了cppreference例子

int main()
{
    std::vector<int> v = {0,1,2,3,4,5,6,7,8,9};
    std::cout << "Original vector:\n    ";
    for(int elem : v) std::cout << elem << ' ';
 
    auto it = std::partition(v.begin(),v.end(),[](int i){return i % 2 == 0;});
 
    std::cout << "\nPartitioned vector:\n    ";
}

原始向量: 0 1 2 3 4 5 6 7 8 9
分割向量: 0 8 2 6 4 * 5 3 7 1 9

但是我仍然不明白为什么在这个例子中顺序总是相同的。 std::vector中的所有元素都保存在堆中,并且只有在没有重新分配的情况下,std::vector才能保证元素的迭代器和地址的稳定性。 在std :: partition之后,违反了此保证,因此顺序可以不同,但​​为什么总是 0 8 2 6 4

还是我错了,并且std :: vector元素的内存可视化有问题?

解决方法

如果我们从cppreference看可能的实现,我们会看到它的确定性(如果UnaryPredicate是确定性的)。

template<class ForwardIt,class UnaryPredicate>
ForwardIt partition(ForwardIt first,ForwardIt last,UnaryPredicate p)
{
    first = std::find_if_not(first,last,p);
    if (first == last) return first;
 
    for (ForwardIt i = std::next(first); i != last; ++i) {
        if (p(*i)) {
            std::iter_swap(i,first);
            ++first;
        }
    }
    return first;
}

毫无疑问,它每次都会对相同的输入执行相同的操作。前两行仅是对源进行了部分分区的优化。