【问题标题】:Passing array to class function C++将数组传递给类函数 C++
【发布时间】:2015-09-15 05:16:17
【问题描述】:

我有一个组织为

的二维数组
float vertices[3][3]

在我的程序的一个迭代循环中,我在调试器中看到数组已填满:

vertices[0] = {-1, -1, 1}
vertices[1] = {-1, -.5, .5}
vertices[2] = {-.5, -1, .5}

然后我将三个顶点传递给我的三角形类。

Triangle *t = new Triangle(vertices[0], vertices[1], vertices[2]);
triangles.push_back(*t);

三角形构造函数编码如下:

Triangle::Triangle(float *a, float *b, float *c)
{
    memcpy(v1, a, sizeof(a));
    memcpy(v2, b, sizeof(b));
    memcpy(v3, c, sizeof(c));
}

我的调试器现在显示

v1 = {-1, -431602080, -431602080}
v2 = {-1, -431602080, -431602080}
v3 = {-.5, -431602080, -431602080}

调试器还显示 a/b/c 只有 1 个元素长? 那么显然只有数组的第一个元素被传递?

【问题讨论】:

  • 还需要传递数组的大小!

标签: c++ arrays function class


【解决方案1】:

大小(a)

其实是

sizeof (float*)

这不是 3x 浮点数,它是 1 个指针。传递附加参数 size_t number_of_members_in_array 并替换

memcpy(v1, a, sizeof(a));

与

memcpy(v1, a, sizeof(*a) * number_of_members_in_array);

Triangle::Triangle(float *a, int numA, float *b, int numB, float *c, int numC)
{
    memcpy(v1, a, sizeof(float) * numA);
    memcpy(v2, b, sizeof(float) * numB);
    memcpy(v3, c, sizeof(float) * numC);
}

【讨论】:

  • 这种方法(或使用 std::vector)也将帮助您稍后将顶点转换为非常流行的 4 元素版本: where w = 0 : 点和 w=1 : 向量。
  • 有趣的是,如果你用“float a[3];”之类的代码编写,那么 sizeof(a) 将是 3*sizeof(float),尽管它不会影响你的问题
  • 它是函数的签名(参数类型)。他仍然可以用``float[3] a``代替float*a来写它。尽管从来没有人这样做过,我什至忘记了为什么通常会避免这种情况,因为我自己从永恒以来就一直避免这样做。
【解决方案2】:

这里的问题是您使用sizeof 运算符,因为一旦数组衰减到指针,它就会丢失所有大小信息,并且在函数中执行例如sizeof(a) 只会给你指针的大小,而不是它指向的地方。

在 C++ 中有一个简单的方法可以解决这些问题,那就是使用 std::vector 或 std::array 来代替。如果您出于某种原因不想使用那些方便的类,那么您需要以某种方式将大小传递给函数,例如参数或模板参数。

【讨论】:

    【解决方案3】:

    在你的情况下,sizeof(a) 会给你指针的大小,而不是它指向的数据。这是因为a 是一个float 指针!

    这样做: 将元素数量(在您的情况下为 3)作为参数传递:

        Triangle::Triangle(float *a, float *b, float *c, int numElements)
        {
            memcpy(v1, a, sizeof(a) * numElements);
            memcpy(v2, b, sizeof(b) * numElements);
            memcpy(v3, c, sizeof(c) * numElements);
        }
    

    【讨论】:

      【解决方案4】:

      另一种方法是预期的固定大小的浮点数组:

      Triangle::Triangle(const float (&a)[3], const float (&b)[3], const float (&c)[3])
      

      但传递size 或使用std::array<float, 3> 或std::vector<float> 似乎更简单。

      【讨论】:

        【解决方案5】:

        除了其他解决方案,我想指出您的代码存在内存泄漏:

        Triangle *t = new Triangle(vertices[0], vertices[1], vertices[2]);
        triangles.push_back(*t);
        

        当您push_back(*t) 时,您正在将分配对象的副本推送到*t,而不是指针t 的副本。该向量在内部为另一个Triangle 分配空间并将给定的对象复制到其中。在此代码之后,该指针丢失并且分配的对象被孤立/泄漏。

        如果您打算将三角形保留为单独分配的对象,那么 triangles 应该是 vector<Triangle *> 并且代码应该如下所示:

        Triangle *t = new Triangle(vertices[0], vertices[1], vertices[2]);
        triangles.push_back(t);
        

        如果您打算将triangles 保留为vector<Triangle>,那么您需要更多类似的东西:

        Triangle t(vertices[0], vertices[1], vertices[2]);
        triangles.push_back(t);
        

        或者,如果你的编译器/stl 实现支持vector::emplace_back(),那就更简单了:

        triangles.emplace_back(vertices[0], vertices[1], vertices[2]);
        

        哪个构造直接进入向量中的新条目。

        【讨论】:

          猜你喜欢
          • 2018-11-14
          • 2013-06-26
          • 2014-06-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多