这是一个基本的指针问题,但这让我感到困惑一段时间了。我使用C ++实现了加权图 map 作为基础数据架构,如下:

std::map<int, std::vector<Edge> > edgeList;

该地图保存节点ID(一个 int)作为键和该节点上的边缘列表 vector 作为值

我已经初始化了每个节点的边缘列表,如下所示:

for(int i = 0; i< n; i++){
        std::vector<Edge> vi;
        edgeList.insert(std::make_pair(i,vi)); // initialize with empty vector (at least, that's the intent)
    }

现在,在图表中添加边缘时,当我尝试检索边缘列表时 vector 对应于每个节点如下:

std::vector<Edge> vList = edgeList.at(v); // v is the node id here

一个空 vector 即使我已经返回了VLIST,即使我较早地将边缘添加到了该VLIST中。

另一方面,

std::vector<Edge> &vList = edgeList.at(v);

似乎为我的目的工作正常。谁能解释一下为什么第一个实施不起作用,而第二个实现?

编辑:将边缘添加到图的代码如下:

void Graph::addEdge(Edge e){

    // retrieve start and end node for this edge
    int v = e.either(); // returns either end of the edge
    int w = e.other(v);

    // retrieve edge lists for these nodes
    std::vector<Edge> vList = edgeList.at(v); // doesn't work
    std::vector<Edge> wList = edgeList.at(w); // doesn't work

    // add this edge to the list of edges
    vList.push_back(e);
    wList.push_back(e);
}
有帮助吗?

解决方案

std::map::at 功能返回对 std::vector 在给定索引。当您将其分配给非参考变量时,您将制作向量的副本。您执行的任何插入操作都将在矢量的副本上,该矢量在方法的末尾不在范围,而您的目标是您瞄准的矢量却快乐地坐在地图中,并且不受影响。

相反,如果您添加 &, , 然后 vList 真正将成为存储在地图中的实际矢量的别名。现在,对 vList 真的是对地图元素制作的。如果愿意,可以将参考视为伪装的指针。在这种情况下,您会明确写

std::vector<Edge> *vList = &edgeList.at(v);

例如,不是

std::vector<Edge> *vList = new std::vector();
*vList = edgeList.at(v);

实际上,以下示例更清楚地证明了这一点:

using namespace std;

int i = 0;

int& get_i()
{
    return i;
}

int main()
{
   cout << "i = " << i << ", &i = " << &i << endl;

   int j = get_i();
   j++;
   cout << "i = " << i << ", j = " << j << ", &j = " << &j << endl; 

   int& k = get_i();
   k++;
   cout << "i = " << i << ", k = " << k << ", &k = " << &k << endl; 

   return 0;
}

其他提示

当您这样做时:

std::vector<Edge> vList = edgeList.at(v);

您正在创建一个 复制 地图中的向量。

当您这样做时:

std::vector<Edge> &vList = edgeList.at(v);

您将获得该向量的引用。

如果将元素添加到副本中,则不会将它们添加到地图中(因为它只是一个副本,并且与原始内容无关)。如果将元素添加到引用中,则将其添加到地图中,因为它是相同的向量。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top