是什么导致这个向量下标超出范围错误?



我目前正在将一个Graph映射到扫雷类网格,其中每个Block代表一个节点。这是我的Graph类:

class Graph : public sf::Drawable
{
public:
Graph(uint32_t numNodesWidth, uint32_t numNodesHeight);
[[nodiscard]] std::vector<Node> & operator[](std::size_t i) 
{ return data[i]; }

[[nodiscard]] sf::Vector2u dimension() const 
{ return {static_cast<uint32_t>(data.size()), 
static_cast<uint32_t>(data[0].size())};}
...
...
private:
std::vector<std::vector<Node>> data;
};
下面是构造函数的实现:
Graph::Graph(uint32_t numNodesWidth, uint32_t numNodesHeight)
{
data.resize(numNodesHeight);
for(auto & row : data)
{
row.resize(numNodesWidth);
}
}

在另一个类中,我读取鼠标坐标并将其转换为"图形坐标":

sf::Vector2u translatedCoords = toGraphCoords(sf::Mouse::getPosition(window), nodeSize_);
bool inBounds = checkGraphBounds(translatedCoords, graph.dimension());
以下是辅助函数:
sf::Vector2u toGraphCoords(sf::Vector2i mouseCoord, sf::Vector2f nodeSize)
{
return {static_cast<uint32_t>(mouseCoord.y / nodeSize.y), 
static_cast<uint32_t>(mouseCoord.x / nodeSize.x)};
}
bool checkGraphBounds(sf::Vector2u mouseCoord, sf::Vector2u bounds)
{
return mouseCoord.x >= 0 && 
mouseCoord.y >= 0 && 
mouseCoord.x < bounds.x && 
mouseCoord.y < bounds.y ;
}

当我尝试使用这些新的检查坐标时,我得到了vector subscript out of range 1655错误,这有点奇怪,有人能向我解释我做错了什么吗?当我试图将鼠标悬停在"边界"之外时,这个错误总是显示出来。在第一个或最后一个节点的后面或前面。

提前感谢。

不能保证bounds <= num_nodes * node_size。这是特别危险的,因为涉及到整数除法,这意味着您可以随意舍入。

可以打乱代码,直到这样的保证存在,但有一个更好的方法。

如果checkGraphBounds()函数的运算与网格的运算相同,则可以确定结果将与网格一致,无论它与边界如何相关。

理想的方法是实际使用toGraphCoords()作为它的一部分:

bool checkGraphBounds(sf::Vector2u mouseCoord, const Graph& graph, 
sf::Vector2f nodeSize)
{
auto coord = toGraphCoords(mouseCoord, nodeSize);
return coord.x >= 0 && 
coord.y >= 0 && 
coord.x < graph.dimensions().x && 
coord.y < graph.dimensions().y) ;
}

有了这个,你就可以正式保证如果mouseCoord通过了测试,static_cast<uint32_t>(mouseCoord.x / nodeSize.x)}肯定会返回一个不大于graph.dimensions().x的值。

就我个人而言,我会将这两个函数组合为Graph方法,如下所示:

class Graph : public sf::Drawable {
// Make nodeSize a member of the Graph
sf::Vector2f nodeSize_; 
// This is one of the cases where caching an inferable value is worth it.
sf::Vector2u dimensions_; 
public:
std::optional<sf::Vector2u> toGraphCoords(sf::Vector2i mouseCoord) {
sf::Vector2u coord{
static_cast<uint32_t>(mouseCoord.y / nodeSize_.y), 
static_cast<uint32_t>(mouseCoord.x / nodeSize_.x)};
};
// No need to compare against 0, we are dealing with unsigned ints
if(coord.x < dimensions_.x &&
coord.y < dimensions_.y ) {
return coord;
}
return std::nullopt;
}
// ...
};

用法:

void on_click(sf::Vector2i mouse_loc) {
auto maybe_graph_coord = the_graph.toGraphCoords(mouse_loc);
if(maybe_graph_coord) {
sf::Vector2u graph_coord = *maybe_graph_coord;
// ...
}
}

相关内容

  • 没有找到相关文章

最新更新