使用 vector::reserve 或 vector::resize 时发生了什么

What happened when use vector::reserve or vector::resize

我是 C++14 的用户。 当我使用 std::vector 和比较功能对二维数组进行排序时。 但是并没有像我想的那样起作用,最后我发现了一些奇怪的东西。 让我们看下面的代码。

using namespace std;

int n;
vector<vector<int>> v;

bool cmp(const vector<int>& l, const vector<int>& r){
    return l[1] < r[1] ? true : l[0] < r[0];
}

int main() {
    scanf("%d", &n);
    v.resize(n, vector<int>(2));
    for (int i = 0; i < n; ++i)
        scanf("%d %d", &v[i][0], &v[i][1]);
    sort(v.begin(), v.end(), cmp);
    for(int i = 0; i < n; ++i)
        cout << v[i][0] << ' ' << v[i][1] << endl;
    return 0;
}

(请忽略我使用 scanfcout。我正在解决问题。) 这里是输入

11
1 4
3 5
0 6
5 7
3 8
5 9
6 10
8 11
8 12
2 13
12 14

我预计输出与没有 n 的输入完全相同,但输出是

0 6
1 4
2 13
3 5
3 8
5 7
5 9
6 10
8 11
8 12
12 14

我在修改的时候也发现了奇怪的地方

v.resize(n, vector<int>(2);

v.reserve(n);
    for(int i = 0; i < n; ++i)
        v[i].reserve(2);

reserve 使代码如我所愿。 我想我知道 reserveresizevector 的不同,但缺少一些东西...

你能教我缺少什么吗..?

首先,您的 cmp 功能可能不是您想要的。 例如,它会判断{0, 6}小于{3, 5}。 试试这个:

bool cmp(const vector<int>& l, const vector<int>& r){
    return l[1] < r[1] ? true : (l[1] == r[1] && l[0] < r[0]);
}

或者这个:

bool cmp(const vector<int>& l, const vector<int>& r){
    return l[1] != r[1] ? l[1] < r[1] : l[0] < r[0];
}

其次,std::vector::reserve不会改变向量中元素的数量。 出于这个原因,您通过使用超出范围(不存在)的元素调用了 未定义的行为,并且 偶然得到了结果 .

由于您在编译时知道内部容器的大小,也许您想使用 std::array 代替(或 std::pair 或什至是一个小结构以获得更好的成员变量名称)。另外,不要忘记 for range-based loop,它在容器上迭代时是一种优雅且安全的方法。接下来,您可以在 std::sort 调用中为比较函数使用 lambda。全局变量也被认为是一种不好的做法,因为它违反了封装规则。

#include <iostream>
#include <vector>
#include <array>
#include <algorithm>

int main() {
    std::size_t n;
    std::cin >> n;

    std::vector<std::array<int, 2>> vec(n);
    for (auto& [x, y] : vec)
        std::cin >> x >> y;
    
    std::sort(begin(vec), end(vec), [](const auto& l, const auto& r)
        { return l[1] != r[1] ? l[1] < r[1] : l[0] < r[0]; });

    for (const auto& [x, y] : vec)
        std::cout << x << ' ' << y << '\n';

    return EXIT_SUCCESS;
}