【问题标题】:What happened when use vector::reserve or vector::resize使用 vector::reserve 或 vector::resize 时发生了什么
【发布时间】:2020-11-15 19:46:39
【问题描述】:

我是 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;
}

(请忽略我使用scanf 和cout。我正在解决问题。) 这是输入

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 使代码按我的意愿正确。 我想我知道reserve 和resize vector 的不同之处,但缺少一些东西......

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

【问题讨论】:

  • 您的代码未编译,因为 meeting 未声明。
  • "reserve 使代码如我所愿" - 保留不会将元素添加到向量中,只会添加原始内存。您正在与不存在的向量进行交互。
  • 您的 cmp 实现不遵守严格的弱排序(我不认为)。这是未定义的行为。
  • resize 改变向量的大小,reserve 不会。那就是你缺少的东西。保留为向量分配更多空间,但不会改变它的大小。
  • 谢谢大家。我在你的答案的逻辑中发现了错误。

标签: c++ sorting vector resize


【解决方案1】:

首先,您的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 不会改变向量中元素的数量。 出于这个原因,您通过使用超出范围(不存在)的元素调用了未定义的行为,并且偶然得到了结果。

【讨论】:

  • 你说得对...这只是巧合◡̈这是我对vector::reserve的误解。谢谢!
【解决方案2】:

既然您在编译时就知道内部容器的大小,也许您想改用std::array(或std::pair,甚至是一个小结构来获得更好的成员变量名称)。另外,不要忘记基于范围的循环,在容器上迭代时它是一种优雅且更安全的方法。接下来,您可以在 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;
}

【讨论】:

  • 您的回答非常有帮助,因为我实际上使用的是 java,所以我没有 C++ 的代码审查员。为了我的乐趣,我编写了 c++ 程序。真的真的很感谢你的回答!祝你有美好的一天:)
猜你喜欢
  • 2020-09-22
  • 2011-11-15
  • 1970-01-01
  • 1970-01-01
  • 2019-12-16
相关资源
最近更新 更多