这是一个创建Clustering
对象并按值返回它的方法。
Clustering ClusteringGenerator::makeOneClustering(Graph& G) {
int64_t n = G.numberOfNodes();
Clustering zeta(n);
cluster one = zeta.addCluster();
for (node v = G.firstNode(); v <= n; ++v) {
zeta.addToCluster(one, v);
}
return zeta;
}
此循环多次调用该方法,并将指向返回值的指针添加到 vector 。
int z = 3
for (int i = 0; i < z; ++i) {
// FIXME: why is zeta the same each iteration?
Clustering zeta = clusterGen.makeOneClustering(G);
DEBUG(&zeta);
clusterings.push_back(&zeta);
}
DEBUG语句的输出是
0x7fff4ff894d0
0x7fff4ff894d0
0x7fff4ff894d0
因此,这意味着
&zeta
在每次迭代中都是相同的指针。为什么?如何获得所需的结果(每次迭代创建一个
Clustering
对象并将其记住在 vector 中)? 最佳答案
因为zeta
是一个自动变量(循环中的一个变量,另一个也是局部变量,但是ClusteringGenerator::makeOneClustering
本身没有任何错误),一旦当前循环迭代结束(和zeta
的变量就不再存在)析构函数已被调用)。因此,编译器可以自由地将其底层存储用于其他变量(例如,下一次循环迭代中的zeta
),并且如果不这样做,将非常愚蠢。
同样,您的代码也容易出错,因为它会将局部变量的地址存储在容器中,尽管如上所述,该变量在push_back
之后不再存在。
为了解决这个问题,要么使用std::vector<Clustering>
并按值放入这些东西,要么,如果您确实需要存储指针(也许是因为您不使用C++ 11的移动语义/从中获利,并且担心复制开销) ),然后动态分配这些循环对象,以防止它们被自动破坏。但是在后一种情况下(考虑到Clustering
似乎可以很好地复制,无论如何使用,您都应该彻底考虑一下),而应该使用某种智能指针来照顾对动态分配对象的适当破坏。