如何将大小不同的数组传递给我的C++函数?

4
我不确定是否可能,但我愿意听取建议。
我有一个c++函数。它对由用户定义为输入的数组进行一些计算,并生成两个输出值。让我们称其为“myfunction”,它看起来像这样:
void myfunction(double array1[18],double array[9],double array [2],double *output1, double *output2)
我想使此函数更通用,以便能够接受不同大小的数组。也就是说,我希望该函数的用户能够定义其他大小的数组输入。
例如,
void myfunction(double array1[81],double array[27],double array [3],double *output1, double *output2)
从数学上讲,“myfunction”能够计算出准确的输出,尽管数组大小不同。我不想复制“myfunction”,因为用户可以定义5种不同大小的数组作为输入。
有什么想法吗?谢谢您的帮助。

1
请查看 std::vectorstd::array - Khouri Giordano
2
void myfunction(double array1[18],double array[9],double array [2],double *output1, double *output2) -- 前三个参数不是数组。这个声明与下面的声明完全相同:void myfunction(double *array1, double *array, double *array, double *output1, double *output2);。传递的数组会衰减为指针--在这种形式的声明中,所有的大小信息都会丢失。 - PaulMcKenzie
1
补充@KhouriGiordano的观点,接受std::vector的引用(或者在你不打算修改它时使用const引用)将具有大致相同的性能,并且允许您检查每个输入的.size()以确定需要循环的内容。 - ShadowRanger
1
计划A:使用std::vector。计划B(如果必须使用一维数组):只需不声明大小:void myfunction(double *array1,double *array2,double *array3,double *output1, double *output2) - paulsm4
数组大小在编译时已知吗?输出长度如何计算? - M.M
2个回答

10
您可以传递一个 std::vector 或使用一个 template:
template <std::size_t N1, std::size_t N2, std::size_t N3> // and so on...
void work_with_arrays(double (&arr1)[N1], double (&arr2)[N2], double (&arr3)[N3]){
    std::cout << "First arr of a size: " << N1 << "\n";
    std::cout << "Second arr of a size: " << N2 << "\n";
    std::cout << "Third arr of a size: " << N3 << "\n";
};

int main() {
    double something[32];
    double fewer[13];
    double maybe_byte[8];

    work_with_arrays(something, fewer, maybe_byte);
}

代码输出:
First arr of a size: 32
Second arr of a size: 13
Third arr of a size: 8

解释:

我们应该知道,类型为T[](其中T是任意类型)的参数会衰减T*。如果我们处理指向数组的指针,则无法获取其长度,这是相当不幸的,因为固定长度数组的长度在编译时已知,并且可以在我们与其一起工作的任何地方看到。

我们还应该知道,函数模板不是函数。它是用于创建函数的模板。对于上面例子中使用的每个不同的N#集合,都将生成一个供我们使用的函数。

如何解决衰减问题?

我们应该传递T[]引用,而不是原始的T[]。这样类型就不会衰减,数组的大小也将被知道。

语法?

人们可以注意到T(&name)[some_size]看起来至少很奇怪。需要括号,因为简单的T &name[size]将被解释为T& name[size],这是一个引用数组,而不是数组的引用

结论:

能够检测传递的数组大小,我们不想限制自己只有一两种情况-我们想要涵盖所有这些情况,所以我们使用一个模板来生成具有所需值的N#函数。


1
最好添加细节,比如"double (&arr1)[N1]"是什么以及它是如何工作的,以便"新贡献者"能够轻松理解。 - Swapnil
1
@Swapnil,我编辑了我的答案,添加了对部分问题的解释。 - Fureeish

3
您可以让您的函数接受一个“动态可调整大小的数组”——vector。您可以根据需要迭代它或获取其大小。请查看文档
#include <vector>
using std::vector;  // I'm too lazy to prepend std:: as needed.
void myfunction(const vector<double>& array1, 
                const vector<double>& array2,
                const vector<double>& array3, 
                vector<double>& output1, vector<double>& output2) {

}

如果不可能的话,那么就让它接受额外的参数来指示数组的大小。
void myfunction(double *array1,
                double *array2, 
                double *array3,
                int size1,
                int size2,
                int size3,
                double *output1, 
                double *output2) {

}

但这真的很丑陋。就选择第一个选项吧。


第二种方法不仅“丑陋”,而且如果大小不正确,客户端很容易犯错误。使用vector::size()函数,vector可以知道其大小,因此永远不会出错。 - PaulMcKenzie
@PaulMcKenzie 完全同意。然而,现实情况是,有些平台或限制有时会禁止使用复杂的数据结构(虽然向量并不是那么复杂),有时还要处理不能轻易重构的遗留代码,因此这是一个非常绝望的选择。 - lightalchemist
在这些情况下,如果可用的话,最好使用带有灵活数组成员的结构体。 - Cinder Biscuits
@CinderBiscuits 是的。忘记了这个。实际上,这带来了另一个选择,即对接受 std::array 作为参数的函数进行模板专门化。本质上是 @Fureeish 的答案,但没有使用原始指针。 - lightalchemist

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