我正面临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 函数的声明而不更改其代码 - 因此也应考虑这一点。请参阅与使用迭代器的解决方案相关的答案。
答案 0 :(得分:3)
一个优雅的解决方案是使Compute()接受迭代器而不是指针。您提供的迭代器将具有足够的++运算符(请参阅boost::iterator
以获得构建它们的简便方法)
Compute(MyIterator x, MyIterator y, MyIterator z);
通常对函数体进行的更改很少,因为*x
,x[i]
或++x
将由MyIterator
处理以指向正确的内存位置
不太优雅但更直接的解决方案是将数据保存在以下结构
中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;
}
}
我认为这是一个丑陋的解决方案 - 改变您访问数据的方式可能会“更好”。