使用 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;
}
(请忽略我使用 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
的不同,但缺少一些东西...
你能教我缺少什么吗..?
首先,您的 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;
}
我是 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
的不同,但缺少一些东西...
你能教我缺少什么吗..?
首先,您的 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;
}