0

使用参考。std::generate 的行为应该等同于:

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

但是当我尝试用 0-99 数字填充矩阵时。相反,我得到 10 行 0-9。这是为什么?

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

3

您也可以使用std::ref来防止生成器对象的复制:

generate(begin(v), end(v), std::ref(generator));
于 2013-10-07T07:52:00.943 回答
2

因为你的生成器是根据签名复制的

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

即您保留自己的副本,std::generate也可以。每次你传递你自己的,因此未修改generatorstd::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,则传递 lambda 函数,该函数通过引用increment获取自动变量。int i = 0;对于每次调用for_each,它都会创建一个新的increment仿函数,但i不会重置而是递增;因此您会看到这些值是连续的。lambda 函数 ( ) 的内存i在它自己的域之外,即在父函数 main 中。

如果是您自己的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 回答