向量下标超出函数范围
Posted
技术标签:
【中文标题】向量下标超出函数范围【英文标题】:Vector subscript out of range in function 【发布时间】:2020-07-28 22:04:04 【问题描述】:我在这个背包函数中使用了一个二维向量,它不断返回超出范围的向量(第 1733 行),但是向量不应该超过它们的大小并导致溢出。将 for 循环更改为
int knapsack(int cap, vector<int>& weight, vector<int>& value, int n)
vector<vector<int>> K;
K.resize(cap, vector<int>(n));
int i = 0;
int j = 0;
for (i = 0; i <= n; i++)
for (j = 0; j <= cap; j++)
if (i == 0 || j == 0)
K[i][j] = 0;
else if (weight[i - 1] <= j)
K[i][j] = max(weight[i - 1] + K[i - 1][j - weight[i - 1]], K[i - 1][j]);
else
K[i][j] = K[i-1][j];
return K[i][j];
据我了解,调整大小将是解决方案,但我已经使用向量大小的适当变量完成了该操作。还是我需要使用 pushback 代替?
【问题讨论】:
"向量不应该超过它们的大小并导致溢出" - 你当然认为你的程序是正确的,但是你和其他人一样会犯错误。您的向量是cap
by n
,但您将其索引为n
by cap
。 <=
也是一个错误。
仅仅因为改变某些东西并不能解决问题并不意味着它不是错误。这只是意味着它不是唯一的错误。当你调试时,不要假设错误在哪里,因为你有一个错误首先表明你可能是错误的。
<=
在 for 循环中总是引发我的蜘蛛感。
【参考方案1】:
矢量索引
当你声明K
如下:
vector<vector<int>> K;
K.resize(cap, vector<int>(n));
那么向量K
的长度为cap
,每个向量K[i]
的长度为n
。但是,在您的 for 循环中,我看到:
for (i = 0; i <= n; i++)
for (j = 0; j <= cap; j++)
if (i == 0 || j == 0)
K[i][j] = 0;
...
这里的索引顺序似乎是错误的,因为在if
-statement 中,您可以设置K[n][0]
或K[0][cap - 1]
,此时唯一有效的最大索引是K[cap - 1][0]
和K[0][n - 1]
.
使用push_back()
更安全。在这种情况下,不要忘记预留空间以避免不必要的重新分配。
循环范围
正如 cmets 中的其他人所提到的,在迭代 n
元素时,正确的写法是:
for (i = 0; i < cap; ++i)
所以没有'
循环结束后,迭代器将指向循环结束之外
一旦像for (i = 0; i < cap; ++i)
这样的循环完成,它会将i
增加到值cap
。所以最后一行:
return K[i][j];
肯定会访问超出范围的向量。你应该这样写:
return K[cap - 1][n - 1];
或者,您可以使用成员函数back()
访问向量的最后一个元素,并编写:
return K.back().back();
未使用的函数参数
为什么在这个函数中根本没有使用参数value
?
断言weight
具有正确的大小
访问超出范围的向量的另一个可能来源是向量weight
的大小不正确。您可以在代码中添加assert()
以在调试版本中发现此错误:
#include <cassert>
...
int knapsack(int cap, vector<int>& weight, vector<int>& value, int n)
assert(weight.size() >= n - 1);
...
【讨论】:
所以我将它们反转为 K.resize(n, vectorn+1
和 cap+1
,因为您的 for 循环使用 <=
作为其限制以上是关于向量下标超出函数范围的主要内容,如果未能解决你的问题,请参考以下文章