在C++中返回一个浮点数数组

5

我目前在C++中有一个4x4矩阵类,每个值都以浮点数形式存储:

Matrix4d::Matrix4d(const float& m00, const float& m01, const float& m02, const float& m03,
                   const float& m10, const float& m11, const float& m12, const float& m13,
                   const float& m20, const float& m21, const float& m22, const float& m23,
                   const float& m30, const float& m31, const float& m32, const float& m33)
{
    _m00 = m00;
    _m01 = m01;
    _m02 = m02;
    _m03 = m03;
    _m10 = m10;
    _m11 = m11;
    _m12 = m12;
    _m13 = m13;
    _m20 = m20;
    _m21 = m21;
    _m22 = m22;
    _m23 = m23;
    _m30 = m30;
    _m31 = m31;
    _m32 = m32;
    _m33 = m33;
}

我的问题是,如何返回一个浮点数组来表示这些数据?我在类中创建数组没有问题,例如:
float arrayToReturn[16] = { m00, m01, m02, m03, ... m33 };

然而,我无法从类中返回此值。我已经阅读了有关返回指向数组的指针的内容,但没有成功。

5个回答

4
  1. 不要通过const引用传递浮点数,而是通过值传递。

  2. 我假设你想返回数组以便进行索引?那么不要从矩阵类中返回一个数组。相反,重载[]运算符或其他东西。

  3. 此外,我不会使用16个成员变量,而是使用一个数组。这样可以更轻松地进行索引。

以下是我可能会采取的方式:

class Matrix4d
{
    float matrix[4][4];

public:

    Matrix4d(float m00, float m01, float m02, float m03,
             float m10, float m11, float m12, float m13,
             float m20, float m21, float m22, float m23,
             float m30, float m31, float m32, float m33)
    {
        matrix[0][0] = m00;
        matrix[0][1] = m01;
        matrix[0][2] = m02;
        matrix[0][3] = m03;
        matrix[1][0] = m10;
        matrix[1][1] = m11;
        matrix[1][2] = m12;
        matrix[1][3] = m13;
        matrix[2][0] = m20;
        matrix[2][1] = m21;
        matrix[2][2] = m22;
        matrix[2][3] = m23;
        matrix[3][0] = m30;
        matrix[3][1] = m31;
        matrix[3][2] = m32;
        matrix[3][3] = m33;
    }

    float* operator[](int i)
    {
        return matrix[i];
    }

    const float* operator[](int i) const
    {
        return matrix[i];
    }
};

int main()
{
    Matrix4d test(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 16);
    test[3][2] = 15;
}

+1,特别是数组建议。@james:除非你正在编写高性能应用程序(例如3D游戏或加密应用),否则请考虑使用“vector”类。它实现了许多你原本需要自己实现的功能。 - outis
感谢您的输入,我正在为移动设备创建一个3D游戏!我制作自己的矩阵类的唯一原因是为了能够返回一个1D数组并调用glMultMatrixf,同时也可以使用它来计算我的矩阵方程。现在它运行得很好!@Fred 为什么我不应该通过const传递浮点数? - ingh.am
因为传递浮点数的引用所需的信息量永远不会比浮点数本身更小,而且额外的间接层可能会影响性能。通过const引用传递浮点数并没有任何好处。 - fredoverflow
好的,谢谢你。我只是按照我在大学里学到的知识去做这件事! - ingh.am
我同意使用2D数组可能是一种更好的存储方式,谢谢。 - ingh.am
你应该已经学过“传递原始类型的值,而将太昂贵以至于无法复制的对象作为const引用传递”;-) - fredoverflow

3
这将适用于您的内部数组看起来像 float array[4][4] 的情况:
float** Matrix4d::getMatrix();

如果您的内部数组是一维数组:
float* Matrix4d::getMatrix();

但这两种情况都会将你的类的内部机制暴露给外部世界,这使得你的代码不太安全,也更难维护。

最好为你的Matrix4d类创建一个复制构造函数、一个()运算符和一个赋值运算符,并将其传递。这样做会减少由于错误的内存管理或数据损坏而导致的运行时错误。

你的()运算符应该像这样:

float& operator()( unsigned int xIndex, unsigned int yIndex )
{
  //return the right attribute
}

您可以这样调用来设置值:
aMatrix(0,0) = 2.0;

或者使用以下方法来检索:

float attributeCopy = aMatrix(0,0);

它可以双向工作。

编辑:忘记了[]操作符只接受一个参数,将操作符更改为()操作符,也称为函数操作符。


该运算符在C++语言中不存在。 - Jasper Bekkers
1
不,那样行不通。如果x没有重载逗号运算符,a[x, 0]将等同于a[0]。我也不确定你的float **方式:使用该函数声明肯定无法返回arrayToReturn - Johannes Schaub - litb
更新了答案以澄清getMatrix函数的返回值。 - thebretness
@thebretness,不要使用float x[4][4]; return x;这样的函数声明,它肯定是行不通的。你需要将返回类型更改为float(*)[4]。例如:identity<float[4]>::type *getMatrix(); - Johannes Schaub - litb
thebretness,你的实现与const矩阵不兼容。此外,自动生成的复制构造函数和赋值运算符已经完全满足要求,手动定义它们是不必要的。 - fredoverflow
显示剩余4条评论

2
你可以使用联合体来描述你的类。
union
{
    struct
    {
       float _m00;
       float _m01;
       ...
    };
    float _m[16];
};

你可以返回 _m。
另外,获取cols也可能很有用,因此:
union
{
    struct
    {
       float _m00;
       float _m01;
       ...
    };
    float _m[4*4];
    float _cols[4][4];
};

虽然我不建议在C++中这样做(有更加用户友好和直观的方法可以实现此目标),但对于C语言,这是一个很好的解决方案。 - zeboidlund

1

我能想到三个选项。

第一个是返回 std::vector 而不是数组。 用户始终可以通过 &v[0] 获取内部数组的指针。

std::vector<float> Matric4d::getData() { 
  std::vector<float> d(16); 
  d[0]=_m00; 
  ... 
  return d;
}

第二种方法是返回一个boost::array。(如果你的编译器支持类似的东西,我认为在即将到来的C++0x标准中有一个tr1::array)再次很容易访问内部数组。

第三种方法是最不正规的,但如果你需要速度可能是最好的。如果你连续存储你的浮点数,你可以返回指向第一个条目的指针。(注意,你需要小心你的类的细节,否则你会得到“未定义行为”。然而,许多/大多数/所有编译器仍然会“做正确的事情”。)哦,你需要小心,因为指针只在矩阵仍然存在时有效。

float * Matrix4d::getData() { return &_m00; }

确实如此。数组索引只是伪装成指针算术的形式。对于指向单个元素(而不是数组)的指针进行指针算术是未定义的行为。 - fredoverflow

1

只需访问第一个元素的地址。

inline float* asArray {
  return &_m00 ;
}

您可以将任何结构体视为数组

Matrix4d matrix ;
// init with values..

functionThatExpectsArrayOfFloat( &matrix._m00 ) ;

感谢您的反馈。虽然我已经有两年没有关注过这个项目,但我会在未来应用它 :D 谢谢。 - ingh.am
那里已经有一个相当不错的答案,比你早两年发布了! - ingh.am

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接