我有一个C ++类,包含一堆相同类型的数据成员,我想迭代它们:
// C.h
class C {
// other members
double foo;
double bar;
...
double barf; // 57th double declared since foo, nothing else in between
// other members
};
指针算法似乎有用,例如这里使用构造函数初始化那58个成员的双打:
// C.cpp
C::C() {
for (int i = 0; i < 58; i++) {
*(&this->foo + i) = 0;
}
}
我在How to iterate through variable members of a class C++,C++: Iterating through all of an object's members?,此处Are class members garaunteed to be contiguous in memory?以及此处Class contiguous data找到了相关问题,有些人认为这种事情还可以,其他人则不没有。后者说不能保证它不会失败,但不要引用它实际上失败的任何实例。所以我的问题是,是否有其他人使用过这个,或者已经尝试过并遇到麻烦了?
或许还有更好的方法?最初在我的应用程序中,我实际上使用数组代替我的对象,索引如下:
int i_foo = 0, i_bar = 1, ..., i_barf = 57;
然而,一旦我引入了不同的对象(及其数组),索引命名开始失控。另外我想学习课程,我希望其他一些功能可以证明有用; - )
我非常重视迭代,例如计算对象集合的统计信息。当然,我可以创建一个函数来逐个将类成员映射到一个数组,但性能是一个优先事项。我正在为自己开发这个应用程序,以便在Windows上使用VS.我想保持其他平台选项开放,但这不是我打算广泛分发的东西。感谢
答案 0 :(得分:3)
乔治:
我认为你可以有更好的解决方案(比如将返回第i个属性的方法:
double get(size_t idx)
{
switch (idx)
{
case 0: return foo;
case 1: return bar;
case 2: return foo_bar;
....
}
}
答案 1 :(得分:0)
使用指针算法迭代类数据成员可能会在代码优化期间导致问题。例如:
struct Vec3
{
double x, y, z;
inline Vec3& operator =(const Vec3& that)
{
x = that.x;
y = that.y;
z = that.z;
return *this;
}
inline double& operator [](int index)
{
return (&x)[index];
}
};
...
Vec3 foo = bar; // operator =
double result = foo[2]; // operator []
...
两个运算符都是内联的,结果的值取决于最终的指令重新排序。可能的情况:
foo.x = bar.x;
foo.y = bar.y;
foo.z = bar.z;
result = (&foo.x)[2]; // correct -- result contains new value
foo.x = bar.x;
foo.y = bar.y;
result = (&foo.x)[2]; // incorrect -- result contains old value
foo.z = bar.z;
foo.x = bar.x;
result = (&foo.x)[2]; // incorrect -- result contains old value
foo.y = bar.y;
foo.z = bar.z;
有些编译器没有意识到(&amp; foo.x)[2]与foo.z的数据相同,并且他们不正确地重新排序指令。很难找到这样的bug。