首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在循环中创建对象

在循环中创建对象
EN

Stack Overflow用户
提问于 2013-01-08 23:10:11
回答 4查看 972关注 0票数 1

下面是一个创建Clustering对象并按值返回它的方法。

代码语言:javascript
复制
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;
}

此循环多次调用该方法,并将指向返回值的指针添加到向量中。

代码语言:javascript
复制
    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);
    }

调试语句的输出为

代码语言:javascript
复制
0x7fff4ff894d0
0x7fff4ff894d0
0x7fff4ff894d0

所以这意味着&zeta在每次迭代中都是相同的指针。为什么?我怎样才能得到想要的结果(每次迭代创建一个Clustering对象并在向量中记住它)?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-01-08 23:15:27

因为zeta是一个自动变量(循环中的那个,好吧,另一个也是局部变量,但ClusteringGenerator::makeOneClustering本身没有什么问题),一旦当前循环迭代结束(并且调用了zeta的析构函数),它就不再存在了。因此,编译器可以自由地重用它的底层存储来存储更多的变量(比如下一次循环迭代中的zeta ),而不这样做将是非常愚蠢的。

同样,您的代码也容易出错,因为它将局部变量的地址存储在容器中,尽管该变量在push_back之后不再存在,如上所述。

要解决这个问题,要么使用std::vector<Clustering>并按值将这些内容放入,要么如果你真的需要存储指针(可能是因为你不使用C++11的移动语义并担心复制开销),那么动态分配这些循环对象,以防止它们被自动销毁。但在后一种情况下(考虑到Clustering似乎具有很好的可复制性,您无论如何都应该仔细考虑它的用法),您应该使用某种智能指针来关注动态分配对象的正确销毁。

票数 2
EN

Stack Overflow用户

发布于 2013-01-08 23:25:25

你可以定义

代码语言:javascript
复制
std::vector<Clustering> clusterings;

然后使用

代码语言:javascript
复制
clusterings.push_back(clusterGen.makeOneClustering(G));

如果您使用的是c++11,并且集群是可移动的,那么您甚至不需要生成副本。这种解决方案速度更快,而且您不必处理原始指针。

票数 1
EN

Stack Overflow用户

发布于 2013-01-08 23:22:29

这是因为您打印出的是您创建的变量的地址,而它始终是相同的。向量也是如此。您存储的是地址,而不是实际值。如果您想存储值,请尝试使用此命令。

代码语言:javascript
复制
clustering.push_back(zeta);

现在您存储的是值,而不是地址...

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14218005

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档