【问题标题】:Convert class to fixed-length float array将类转换为固定长度的浮点数组
【发布时间】:2016-05-24 21:16:23
【问题描述】:

如何将以下类转换为定长浮点数组?

class Vertex
{
public:
    Vertex( float x = 0,
            float y = 0,
            float z = 0)
    : x(x), y(y), z(z) {}

    float x, y, z;
};

例如,我想这样使用它:

Vertex v(0, 1, 0);
float arr[3] = v; // How to convert here?

谢谢!


编辑:

我应该在发布这个问题之前添加一些背景信息。

我使用 C 风格数组的原因是因为我想将高级顶点对象组合成一个 顶点数组 以使用 OpenGL 进行渲染,据我所知需要一个集合原始数组 (float[3]) 或结构。

为此,我认为user2079303's answer 是最佳选择。但是,如果存在更优雅的解决方案,那就更好了。 :)

【问题讨论】:

  • 您是否尝试过添加转换运算符? en.cppreference.com/w/cpp/language/cast_operator
  • @Alex 我不同意这个骗局。它没有解释如何初始化一个数组类型。
  • 你必须有一个原始数组还是可以使用std::array
  • @NathanOliver 我没有在问题中提到这一点。现在添加了一些背景信息...

标签: c++


【解决方案1】:
#include <iostream>
#include <array>

using namespace std;

class Vertex
{
public:
    Vertex( float x = 0,
            float y = 0,
            float z = 0)
    : x(x), y(y), z(z) {}

    operator array<float, 3>() const {
        return {x,y,z};
    }
    /* See @user2079303's answer for a compile-time check of the array dimension */
    void fillArray(float arr[3]) {
        arr[0] = x;
        arr[1] = y;
        arr[2] = z;
    }

    float x, y, z;
};

int main() {
    Vertex v(1,1.4,2);

    array<float, 3> arr = v;

    float arr2[3];
    v.fillArray(arr2);

    for (int i = 0; i < 3; i++) {
        cout << arr[i] << " " << arr2[i] << endl;
    }
    return 0;
}

Live Demo

std::array 与使用 C 样式数组一样高效,不会损失任何性能。您也可以改用std::vector

你不能只返回和复制一个数组,即使在 C 中也是如此。这就是为什么如果你绝对想使用一个 C 数组,你必须有一个像 fillArray 这样的函数。

【讨论】:

  • 请注意,fillArray(float arr[3]) 在编译时无法检测到用户传递了一个太小的数组,这有点危险——它与fillArray(float arr[]) 相同,与fillArray(float* arr 相同。
【解决方案2】:

类不能转换为(原始)数组,因为强制转换运算符必须返回一个数组,这在 c++ 中是不允许的。此外,数组无论如何都不能被复制初始化。

你可以做的是定义一个数组,并将它传递给一个根据对象的内容填充数组的函数:

void Vertex::fill_arr(float (&arr)[3]) {
    arr[0] = x;
    arr[1] = y;
    arr[2] = z;
}

// usage
Vertex v(1, 2, 3);
float arr[3];
v.fill_arr(arr);

另一种选择是使用std::array,它可以正常返回和复制初始化。

【讨论】:

  • 谢谢!我接受了你的回答,因为它包括编译时检查
【解决方案3】:

您有很多选择,而您选择的选择很大程度上取决于上下文。以下是“转换”顶点的四种不同方法:

class Vertex
{
public:
    Vertex(float x = 0,
        float y = 0,
        float z = 0)
        : x(x), y(y), z(z) {}

    operator array<float, 3> () const {
        return {x, y, z};
    }

    array<float, 3> array_copy() const {
        return {x, y, z};
    }

    unique_ptr<float[]> c_array_copy() const {
        return unique_ptr<float[]>(new float[3]{ x, y, z });
    }

    void copy_into(float in[3]) const {
        in[0] = x;
        in[1] = y;
        in[2] = z;
    }

    float x, y, z;
};

首先,您可以使用 () 运算符强制转换类:

cout << "Direct access" << endl;
auto as_array = (array<float, 3>)vertex;
cout << as_array[0] << as_array[1] << as_array[2] << endl;

其次,您可以使用 array_copy() 让复制语义为您工作:

cout << "Get a copy" << endl;
auto as_copy = vertex.array_copy();
cout << as_copy[0] << as_copy[1] << as_copy[2] << endl;

第三,你可以获得一个更加c风格的数组副本,其中包含一个指向动态分配数组的唯一指针:

cout << "Get a c-style copy" << endl;
auto as_c_copy = vertex.c_array_copy();
cout << as_c_copy[0] << as_c_copy[1] << as_c_copy[2] << endl;

最后,您可以复制到一个输出参数中:

cout << "Copy onto an out-parameter" << endl;
float copied[3];
vertex.copy_into(copied);
cout << copied[0] << copied[1] << copied[2] << endl;

正如我所说,您选择哪个实际上取决于上下文和性能要求。

请注意,在任何情况下都不能只返回一个 c 样式的数组。

【讨论】:

    【解决方案4】:

    您可以定义一个转换运算符来构造您的数组。另外我建议使用std::array 而不是原始数组。

    #include <array>
    
    class Vertex
    {
    public:
        Vertex(float x = 0.0f, float y = 0.0f, float z = 0.0f)
        : x(x), y(y), z(z)
        {}
    
        float x;
        float y;
        float z;
    
        operator const std::array<float, 3>() const
        {
            return {x, y, z};
        }
    };
    
    int main()
    {
        Vertex v(0.0f, 1.0f, 0.0f);
        std::array<float, 3> arr = v;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-22
      相关资源
      最近更新 更多