这是一个创建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;
}
此循环多次调用该方法,并将指向返回值的指针添加到向量。
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
对象并在向量中记住它?)
答案 0 :(得分:2)
因为zeta
是一个自动变量(循环中的那个,而另一个也是局部变量,但ClusteringGenerator::makeOneClustering
没有任何内在错误),它不再存在一旦当前循环迭代结束(并且已调用zeta
的析构函数)。因此,编译器可以自由地将其底层存储重用于其他变量(例如下一次循环迭代中的zeta
),并且不这样做会非常愚蠢。
同样,您的代码容易出错,因为它将局部变量的地址存储在容器中,尽管此变量在push_back
之后不再存在,如上所述。
要解决这个问题,要么只是使用std::vector<Clustering>
并按值放入这些内容,或者,如果你真的需要存储指针(可能是因为你不使用/利用C ++ 11的移动语义并担心复制开销),然后动态分配这些循环对象,以防止它们被自动销毁。但是在后一种情况下(考虑到Clustering
似乎可以很好地复制,你应该完全过度使用它)你应该使用某种智能指针来关心动态分配对象的正确销毁。 / p>
答案 1 :(得分:1)
你可以定义
std::vector<Clustering> clusterings;
然后使用
clusterings.push_back(clusterGen.makeOneClustering(G));
如果您正在使用c ++ 11并且群集可移动,您甚至不会生成副本。这个解决方案更快,你不必处理原始指针。
答案 2 :(得分:0)
那是因为你打印出你创建的变量的地址,它总是一样的。矢量同样的事情。您正在存储地址而不是实际值。如果要存储值,请尝试使用它。
clustering.push_back(zeta);
现在存储的是值而不是地址....
答案 3 :(得分:-1)
Clustering * ClusteringGenerator::makeOneClustering(Graph& G) {
int64_t n = G.numberOfNodes();
Clustering * zeta = new Clustering(n);
cluster one = zeta.addCluster();
for (node v = G.firstNode(); v <= n; ++v) {
zeta.addToCluster(one, v);
}
return zeta;
}
此循环多次调用该方法,并将指向返回值的指针添加到向量。
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);
}