C ++ 11:使用单范围循环有效地迭代矩阵?

时间:2012-05-31 02:36:07

标签: c++ gcc c++11

(对于具体的编译器/平台上下文,在x86_64上使用GCC 4.7和Ubuntu 12.04)

给出一些函数f:

void f(int x, int y);

int nx = ...;
int ny = ...;

从(0,0)到(nx,ny)迭代每个值(x,y)的一种方法是:

for (int x = 0; x < nx; x++)
    for (int y = 0; y < ny; y++)
        f(x,y);

让这个编译成一些生成的代码Q1。

我们将编写一个函数g:

for (auto it : g(Z))
    f(it.x, it.y);

编译成代码Q2。

是否有可能写出这样的Q2,Q2与Q1一样有效?如果有,怎么样?如果没有,我们能得到的最接近的是什么?

您可以将自动更改为自动&amp;或汽车&amp;&amp;如果它有帮助。

如果有帮助,您也可以将it.x更改为it.x(),it.y更改为it.y()。

(回想一下,基于范围的扩展只是一种类似迭代器的类型:C++11: The range-based for statement: "range-init" lifetime?

2 个答案:

答案 0 :(得分:3)

  

是否有可能写出这样的Q2,Q2与Q1一样有效?如果有,怎么样?如果没有,我们能得到的最接近的是什么?

当然可能,您只需要定义以与for循环相同的方式递增的迭代器。从头到尾:

class matrix_iterator
{
public:
    ...

    matrix_iterator& operator++()
    {
        if( ++y >= ny )
        {
            ++x;
            y = 0;
        }

        return *this;
    }

private:
    int nx, ny;
    int x, y;
};

答案 1 :(得分:2)

此代码具有您需要的功能。我还没有验证它,但我怀疑它会产生与原始循环几乎相同的机器代码(在优化的编译中)。

struct iter {
    int x, y, ny;
    iter(int x, int y, int ny) : x(x), y(y), ny(ny) {}
    iter &operator++ () {
        if (++y >= ny)
        {
            y = 0;
            ++x;
        }
        return *this;
    }
    bool operator != (iter const &rhs) const {
        return y != rhs.y || x != rhs.x;
    }
};

struct container {
    iter endit;
    container(int nx, int ny) : endit(nx, ny, ny) {}
    iter begin() const { return iter(0,0,endit.ny); }
    iter const &end() const { return endit; }
};

container g(Z const &z) { return container(z.nx, z.ny); }

for ( auto it : g(Z) )
    f(it.x, it.y);