1

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反復ごとに1つのオブジェクトを作成し、それをベクトルに記憶します)?

4

4 に答える 4

2

zetaは自動変数 (ループ内の 1 つ、もう 1 つもローカル変数ですが、 には本質的に問題はClusteringGenerator::makeOneClusteringありません) であるため、現在のループ反復が終了すると (そしてのzetaデストラクタがと呼ばれる)。したがって、コンパイラは、(zeta次のループ反復からのように) さらなる変数のためにその基礎となるストレージを自由に再利用できます。

push_back同様に、ローカル変数のアドレスをコンテナーに格納するため、コードはエラーが発生しやすくなりますが、上記のように、この変数は の後に存在しなくなります。

これを解決するには、単に a を使用してstd::vector<Clustering>それらのものを値で入れるか、または本当にポインターを格納する必要がある場合 (おそらく、C++ 11 の移動セマンティクスを使用/利益を得ておらず、コピーのオーバーヘッドを恐れているため) 、次にそれらのループ オブジェクトを動的に割り当てて、それらが自動的に破棄されないようにします。しかし、後者の場合 (かなりうまくコピー可能であるように思われるため、とにかく徹底的に考え直す必要がありClusteringます) 動的に割り当てられたオブジェクトの適切な破棄を処理するために、ある種のスマート ポインターを使用する必要があります。

于 2013-01-08T15:15:26.833 に答える
1

あなたは定義することができます

std::vector<Clustering> clusterings;

その後、

clusterings.push_back(clusterGen.makeOneClustering(G));

c ++ 11を使用していて、クラスタリングが移動可能である場合は、コピーを生成することすらできません。このソリューションはより高速であり、生のポインターを処理する必要はありません。

于 2013-01-08T15:25:25.183 に答える
0

これは、作成した変数のアドレスを出力しているためで、常に同じです。ベクトルと同じこと。実際の値ではなく、アドレスを保存しています。値を保存したい場合は、これを使用してみてください。

clustering.push_back(zeta);

これで、アドレスではなく値を保存しています....

于 2013-01-08T15:22:28.697 に答える
-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);
}
于 2013-01-08T15:21:06.563 に答える