替代阵列表示

时间:2011-03-31 08:26:22

标签: c++ arrays

我正面临C ++的一个问题,我目前没有一个优雅的解决方案。我正在以下列格式接收数据:

typedef struct {
  int x;
  int y;
  int z;
}Data3D;

vector<Data3D> v; // the way data is received (can be modified)

但是执行计算的函数接收如下参数:

Compute(int *x, int *y, int *z, unsigned nPoints)
{...}

有没有办法修改数据接收方式Data3D,以便内存表示形式可以改变:

  

XYZXYZXYZ

  

XXXYYYZZZ

我正在寻找的是以类似的方式填充数据结构的一些方法,我们填充数组但具有上面的表示(XXXYYYZZZ)。欢迎任何自定义数据结构。

所以我想写一些像(在上面的例子中):

v[0].x = 1
v[0].y = 2
v[0].y = 0

v[1].x = 6
v[1].y = 7
v[1].z = 5

并在下面有内存表示

  

... 1,6 2,7 0,5 ....

     

1,6是x数组的开头

     

2,7是y数组的开头

     

0,5是z数组的开头

我知道这可以通过使用临时数组来解决,但我很想知道是否有其他方法可以做到这一点。

谢谢,

尤利安

稍后编辑:

由于某些解决方案仅更改 Compute 函数的声明而不更改其代码 - 因此也应考虑这一点。请参阅与使用迭代器的解决方案相关的答案。

4 个答案:

答案 0 :(得分:3)

基于迭代器的解决方案

一个优雅的解决方案是使Compute()接受迭代器而不是指针。您提供的迭代器将具有足够的++运算符(请参阅boost::iterator以获得构建它们的简便方法)

Compute(MyIterator x, MyIterator y, MyIterator z);

通常对函数体进行的更改很少,因为*xx[i]++x将由MyIterator处理以指向正确的内存位置

Quick'n Dirty solution

不太优雅但更直接的解决方案是将数据保存在以下结构

typedef struct {
  std::vector<int> x;
  std::vector<int> y;
  std::vector<int> z;
}DataArray3D;

收到数据时填写你的结构

void Receive(const Data3D& data, DataArray3D& array)
{
  array.x.push_back(data.x);
  array.y.push_back(data.y);
  array.z.push_back(data.z);
}

并像这样调用Compute(计算本身不变)

Compute(&array.x[0], &array.y[0], &array.z[0]);

答案 1 :(得分:2)

合理优雅(未编译/测试):

struct TempReprPoints
{
  TempReprPoints(size_t size)
  {
    x.reserve(size); y.reserve(size); z.reserve(size);
  }
  TempReprPoints(const vector<Data3D> &v) 
  { 
    x.reserve(v.size()); y.reserve(v.size()); z.reserve(v.size()); 
    for (size_t i = 0; i < v.size(); ++i ) push_back(v[i]);
  }
  void push_back(const Data3D& data)
  {
    x.push_back(data.x); y.push_back(data.y); z.push_back(data.z);
  }
  int* getX() { return &x[0]; }
  int* getY() { return &y[0]; }
  int* getZ() { return &z[0]; }
  size_t size() { return x.size(); }

  std::vector<int> x;
  std::vector<int> y;
  std::vector<int> z;
};

所以你可以用循环来填充它,或者甚至尝试让std :: back_inserter使用它。

答案 2 :(得分:2)

您当然可以更改您的计算机功能。 我假设在计算中的int *上完成的所有操作都是取消引用和递增操作。

我没有测试它,但你可以通过这样的结构

struct IntIterator
{
    int* m_currentPos;
    IntIterator(int* startPos):m_currentPos(startPos){};

    IntIterator& operator++()
    {
        m_currentPos += 3;
        return *this;
    }

    IntIterator& operator++(int)
    {
        m_currentPos += 3;
        return *this;
    }

    int operator*()
    {
        return *m_currentPos;
    }

    int& operator[](const int index)
    {
        return m_currentPos[index*3];
    }
};

用这个

初始化它
std::vector<Data3D> v;
IntIterator it(&v[0].x);

现在您需要做的就是更改计算函数参数的类型,它应该这样做。当然,如果使用一些指针算法而不是变得更复杂。

答案 3 :(得分:1)

为了获得你想要的语法,你可以使用这样的东西。

struct Foo {
  vector<int> x;
    vector<int> y;
    vector<int> z;

    struct FooAccessor {
        FooAccessor(Foo & f, int i) : x(f.x[i]), y(f.y[i]), z(f.z[i]) {}
        int &x, &y, &z;
    };

    FooAccessor operator[](int i) {
        return FooAccessor(*this, i);
    }

};

int main() {
    Foo f;
    f.x.resize(10);
    f.y.resize(10);
    f.z.resize(10);

    f[0].x = 1;
    f[1].y = 2;
    f[2].z = 3;

    for (size_t p = 0; p < 10; ++p) {
            cout << f.x[p] << "," << f.y[p] << "," << f.z[p] << endl;
    }
}

我认为这是一个丑陋的解决方案 - 改变您访问数据的方式可能会“更好”。