3

我正在创建一个需要存储不同数组(如数据)的类。这些数组的大小是可变的,但类中的所有数组都具有相同的大小。这些数组稍后将用于类提供的方法中的数字运算。

在类中声明此类数据的最佳/标准方式是什么?

解决方案 1 – 原始数组

class Example {
    double *Array_1;
    double *Array_2;
    double *Array_3;
    int size; //used to store size of all arrays
};

解决方案 2 –std::vector对于每个阵列

class Example {
    vector<double> Array_1;
    vector<double> Array_2;
    vector<double> Array_3;
};

解决方案 3 -struct存储每个顶点并具有std::vector该结构的A

struct Vertex{
    double Var_1;
    double Var_2;
    double Var_3;
};
class Example {
    vector<Vertex> data;
};

作为初学者,我的结论是:

解决方案 1 的性能最好,但最难实现。

解决方案 3 会更优雅且更易于实现,但在执行某些计算时会遇到问题,因为信息不是数组格式。这意味着接收数组/向量的数字常规函数将不起作用(我需要创建临时向量才能进行数字运算)。

解决方案 2 可能是中途。

对于第四个解决方案的任何想法将不胜感激。

4

3 回答 3

2

不要使用原始数组。选项 2 和 3 是合理的,不同之处取决于您将如何遍历数据。如果您经常单独查看数组,则应将它们存储在解决方案 #2 中,因为每个向量将连续存储在内存中。如果您将通过它们作为点集,那么解决方案 3 可能会更好。如果您想使用解决方案#2,并且始终同步数组(相同大小等)至关重要,那么我会将它们设为私有并通过成员函数控制对它们的访问。例子:

class Example
{
private:
    vector<double> Array_1;
    vector<double> Array_2;
    vector<double> Array_3;

public:
    void Push_data(double val1, double val2, double val3) {
        Array_1.push_back(val1);
        Array_2.push_back(val2);
        Array_3.push_back(val3);
    }

    vector<double> Get_all_points_at_index(size_t index) const {
        if (index < Array_1.size())
            return {Array_1[index], Array_2[index], Array_3[index]};
        else
            throw std::runtime_error("Error: index out of bounds");
    }

    const vector<double>& Get_array1() const {
        return Array_1;
    }

    void Clear_all() {
        Array_1.clear();
        Array_2.clear();
        Array_3.clear();
    }
};

这样,类的用户就不必承担确保他们从所有向量中均匀地添加/删除值的责任——您可以使用您可以完全控制基础数据的类的成员函数来做到这一点。访问器函数的编写应使用户(包括您)无法取消同步数据。

于 2019-07-31T15:26:24.850 回答
1

如果您要处理大量数据,那么解决方案 1 和 2 几乎相同 - 唯一有意义的区别是解决方案 1 难以防止内存泄漏(而解决方案 2 在需要时自动释放您的数据)。

解决方案 2 和 3 之间的区别是人们通常所说的“数组结构”与“结构数组”。这些解决方案的运行时效率取决于您的代码对它们的作用。一般原则是参照的局部性。如果您的代码经常仅对顶点数据的第一个组件进行数字运算,则使用数组结构(解决方案 2)。但是,任何复杂的代码都可以处理所有数据,所以我解决方案 3(结构数组)是最好的。

请注意,这个例子是相当纯粹的。如果您的数据包含有时用于数字运算而有时不使用的元素(例如,它对顶点的两个坐标进行一些转换,而第三个坐标保持不变),那么您可能需要实现某种中间解决方案 - 复制只有需要的数据到某个地方,对其进行转换并将结果复制回来。

于 2019-07-31T15:27:43.230 回答
0

忘记方法 1(正如其他人提到的)并坚持最适合您需求的方法 2 或 3。对我来说,我将您的代码视为管理 3D 空间坐标/数据的应用程序/库的一部分。因此,您应该考虑需要对这些 3D 坐标/数据执行哪些操作,以及哪种方法可以使您的代码更简单或更高效。例如,如果在某些时候您需要将一维的原始数据传递给第三方库(例如用于可视化的东西),您应该采用方法 2。

作为一个具体的例子,VTK(可视化工具包)有很多数据结构,可以以两种方式保存 3D 数据,就像您的第二种方法(请参阅vtkTypedDataArray)或您喜欢的第三种方法(请参阅vtkAOSD​​ataArrayTemplate)。看看它们可能会给你一些想法。

于 2019-07-31T15:42:14.123 回答