C 如何将一系列类别视为主要类型的数组

C++ How to treat an array of classes as an array of primary types?

本文关键字:类型 数组 一系列      更新时间:2023-10-16

我有此代码:

class Vector3
{
    public:
        Vector3() : x(values[0]), y(values[1]), z(values[2])
        { x = y = z = 0; }
        float& x;
        float& y;
        float& z;
    private:
        float[3] values;
};
class Model
{
    public:
        Vector3 vertices[64];
};

我正在执行此矢量类,因为我想在代码中处理值为XYZ的值,但是对于某些操作,我需要一个连续的值数组才能传递给函数。因此,vertices[64]的整个数组需要为[x0][y0][z0][x1][y1][z1][x2][y2][z2]等。

,但是如果我这样做:

//Get first address:
void* firstAddress = &vertices[0];
//Or
void* firstAddress = vertices;

我没有我需要的连续数组(数据都弄乱了),我猜这是因为我在Vector3类中的指针。有什么办法可以获得我想要的此功能?(具有单个浮子数组,但要处理为x,y,z的值)

首先,该标准不能定义应如何实现参考,但是它们几乎可以肯定会在您的班级中占据实际记忆,这是指指针成员会遇到的,破坏了您的连续数据包装您''重新希望....

如果您的重点更多地放在顶点容器上,并且您只希望X/Y/Z成员访问其中的元素,那么您可以尝试以下内容:

template <size_t N>
class Vertices
{
  public:
    class Proxy
    {
      public:
        Proxy(float* p) : x(p[0]), y(p[1]), z(p[2]) { }
        float& x;
        float& y;
        float& z;
    };
    Proxy operator[](size_t n) { return Proxy(&d_[n * 3]); }
    const Proxy operator[](size_t n) const { return Proxy(&d_[n * 3]); }
  private:
    float d_[N * 3];
};

您可以具有成员函数:

class V3
{
    float data[3];
public:
    V3() : data{0,0,0} {}
    float & x() { return data[0]; }
    float & y() { return data[1]; }
    float & z() { return data[2]; }
};

您也可以省略构造函数并具有聚合,如果更合适。

带有3个float参考的values指针的数组(指向3 floats的数组)(xyz)。您可能更像是:

float & x() { return values[0]; }
float & y() { return values[1]; }
float & z() { return values[2]; }

如果我了解您对模型中连续数据的要求,那么您的向量确实是模型中特定数据的特定三重数据的别名。无需浮子存储。

class Model
    class Vector
        Vector(Model *model_, size_t idx_) : model(model_),idx(idx_) { };
        Model *model;
        size_t idx;
        float & x() { return model->data[3*idx]; }
        float & y() { return model->data[3*idx+1]; }
        float & z() { return model->data[3*idx+2]; }
    float data[64 * 3];
    Vector vectors[64];
    Model() {
        ...
        for( size_t ii = 0; ii < 64; ii++ ) {
            vectors[ii] = new Vector(this,ii);
        }
     Vector & vector(size_t idx) { return vectors[ii]; }

对于保证的连续数组,您需要将数据复制到数组中,或使用特定于编译器的保证,尤其是

  • 没有填充物,

,如果您还要以Vector3的实例访问数组的三胞胎,那

  • 在任意地址访问Vector3不会导致陷阱或效率低下(我们进入 Alignment
  • )。

碰巧的是,某些常见库(例如OpenCV)确实为其内部图像缓冲区做出了这样的假设。

,但我不确定我所看到的代码尚未适应平台。因此,实际上您有这些选择:

  • 将数据连续地复制到数组(或从中)和/或

  • 使用提供此类功能的现有库,例如OpenCV。

请注意,使用成员函数而不是引用可以购买任何wrt。对于连续的数组问题,但它确实使Vector3有可能分配。


在进一步的反射上,我可能太触发了以上书写。因为如果您可以保证总尺寸3*sizeof(float),而这几乎是给定的(只需摆脱这些参考),那么您可以保证您可以在任何可以容纳float的地址访问Vector3,因为C 可以保证没有填充的阵列,没有填充,而且由于在这样的数组中,Vector3最终可以在任何可以容纳float的地址处。因此,实践中的问题减少了为支持编译器或编译器配置的决定,这些编译器或编译器配置无法使Vector3大小3*sizeof(float)

即。

struct Vector3
{
    float x, y, z;
    auto operator[]( int i ) -> float& { return (&x)[i]; }
    auto operator[]( int i ) const -> float const& { return (&x)[i]; }
};
static_assert( sizeof( Vector3 ) == 3*sizeof( float ), "Ungood Vector3 size" );

使用没有中间访问说明符的成员可以保证在地址顺序上增加。

免责声明:避免袖口代码,没有由编译器的手触摸。

如果保留vector3类A吊舱,则应该能够简单地将顶点投射到浮点数组:

struct Vector3 {
    float x;
    float y;
    float z;
};
class Model
{
    public:
        Vector3 vertices[64];
        float* data() {
            return reinterpret_cast<float*>(vertices);
        }
};
int main() {
    Model m;
    for(int i = 0; i < 64; ++i) {
        m.vertices[i] = {10+i,100+i,1000+i};
    }
    float *data = m.data();
    for(int i= 0; i < 64*3; ++i) {
        std::cout << data[i] << ", ";
    }
}

唯一的问题可能是结构的反词,但是如果您使用C 11,则使用Allignas alignas(alignof(float[3]))有一种标准方法来对结构进行吻合。我不知道这是否真的需要。另外,C 11给出了有关对vector3的操作的很多选择,同时仍将其视为POD类型。