使用Std::vector::reserve时,Std::sort顺序从大到小

std::sort order is from greatest to least when std::vector::reserve is used?

本文关键字:Std sort 顺序 从大到小 reserve vector 使用      更新时间:2023-10-16

为什么使用vector::reserve会改变排序的行为?

std::vector<unsigned> xyz;
xyz.reserve(3);
xyz[0]=3; xyz[1]=1; xyz[2]=2;
std::sort(xyz.begin(), xyz.end());
std::cout<<xyz[0]<<xyz[1]<<xyz[2]<<"n";
//312
xyz.clear();
xyz.push_back(3); xyz.push_back(1); xyz.push_back(2);
std::sort(xyz.begin(), xyz.end());
std::cout<<xyz[0]<<xyz[1]<<xyz[2]<<"n";
//123

No。这和它没有关系。你的代码将进入未定义行为。

Reserve不允许像下面这样直接使用预留空间:

xyz.reserve(3);
xyz[0]=3; xyz[1]=1; xyz[2]=2;

它只是确保在插入元素时不会重新分配。您没有插入它们,而是使用了一种跳过边界检查的语法。因此,容器不知道元素在容器中。

你可以用at(),它是operator[]的边界检查版本,它会爆炸。

正确的方法是resize或适当插入元素(有几种方法,如emplace, push等)

的例子:

#include <iostream>
#include <vector>
using namespace std;
int main() {
    std::vector<unsigned> xyz;
    xyz.reserve(3); // blows
    // xyz.resize(3);  // works
    xyz.at(0)=3; xyz.at(1)=1; xyz.at(2)=2;
    return 0;
}

我在你的代码中添加了一些注释:

xyz.reserve(3); // only revserve spaces for 3 elements, xyz.size() is still 0
xyz[0]=3; xyz[1]=1; xyz[2]=2; // UB
std::sort(xyz.begin(), xyz.end()); // There's nothing in xyz, so xyz.begin() == xyz.end(), so std::sort sort nothing here
std::cout<<xyz[0]<<xyz[1]<<xyz[2]<<"n"; // UB again

以下代码段

std::vector<unsigned> xyz;
xyz.reserve(3);
xyz[0]=3; xyz[1]=1; xyz[2]=2;

是无效的。如果vector的元素不存在,则不能使用下标操作符。成员函数reserve不创建vector的元素。它只为将来的元素保留内存。在这种情况下,您必须使用push_back而不是下标操作符。或者您可以使用成员函数resize代替保留。与保留相反,它确实创建了vector的指定数量的元素。例如

std::vector<unsigned> xyz;
xyz.resize(3);
xyz[0]=3; xyz[1]=1; xyz[2]=2;