0

参照を使用します。std::generate の動作は次と同等である必要があります。

template <class ForwardIterator, class Generator>
  void generate ( ForwardIterator first, ForwardIterator last, Generator gen )
{
  while (first != last) {
    *first = gen();
    ++first;
  }
}

しかし、マトリックスを0〜99の数字で埋めようとすると。代わりに、0 ~ 9 の 10 行を取得します。何故ですか?

std::vector< std::vector<int> > m;

#ifdef GENERATE
    struct Generator{
        int seq;
        Generator():seq(0){};
        int operator()(){return seq++;};
    } generator;
#elif defined FOR_EACH
    int i = 0;
    auto increment = [&i](int &a){a = i++;};
#endif

int x = 10, y = 10;
m.resize(x);
for(auto &v : m)
{
    v.resize(y);
    #ifdef GENERATE
        generate(begin(v), end(v), generator);
    #elif defined FOR_EACH
        for_each(begin(v),end(v), increment);
    #endif
}
4

3 に答える 3

2

署名に従ってジェネレーターがコピーされるため

void generate ( ForwardIterator first, ForwardIterator last, Generator gen )
                                                  copied ----^^^^^^^^^^^^^

つまり、自分のコピーを保持することもできますstd::generate。独自のものを渡すたびに、したがって変更generatorされずに に渡されますstd::generate。つまり、 counter を持つバージョンで開始するたびに0

Generatorどういうわけか、ファンクターでカウンターを保持し、の使用間で共有する必要があります。

struct Generator{
    int *seq;
    Generator(int &seq):seq(&seq){};
    int operator()(){return (*seq)++;};
};

....

int seq = 0;
generate(begin(v), end(v), Generator(seq));

または同等に

int seq = 0;
generate(begin(v), end(v), [&seq]() { return seq++; });
于 2013-10-07T07:22:58.003 に答える
2

の場合、参照によって自動変数を取るstd::for_eachラムダ関数を渡します。呼び出しごとに新しいファンクターが作成されますが、リセットされずにインクリメントされるだけです。したがって、値が連続していることがわかります。ラムダ関数 ( ) のメモリは、それ自体のドメイン外、つまり親関数 main にあります。incrementint i = 0;for_eachincrementii

独自のgenerate関数の場合、リソースは構造内にあります。つまりGenerator::seq、再初期化されます。を呼び出すたびgenerateに、新しいジェネレータが作成されます。そのコンストラクターseqは 0 に初期化され、毎回カウントがリセットされます。

#ifdef GENERATE
int i = 0;       // lives in main
struct Generator {
    int &seq;
    Generator(int &i):seq(i) { }
    int operator()() { return seq++; }
} generator(i);
#else

ジェネレーターのメモリ部分がより高いレベルにあるため、これは機能するはずです。

于 2013-10-07T07:31:38.783 に答える