在循环中创建对象

时间:2013-01-08 15:10:11

标签: c++ pointers for-loop

这是一个创建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对象并在向量中记住它?)

4 个答案:

答案 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);
}