c++:如何从函数接收可变长度的输出数组

c++: How to receive variable length output array from a function

本文关键字:数组 输出 函数 c++      更新时间:2023-10-16

我正在用C++编写一个包装器,它调用另一个C++函数。但该函数的输出是一个可变长度的数组。不幸的是,数组大小需要是编译时常数。

当前我所拥有的:

double output[5];
mycustomfunction(input1,input2,input3,output);
for(unsigned i=0;i<(sizeof(output)/sizeof(double));i++)
   cout << ',' << output[i];

但在运行函数之前,我不知道输出的大小是多少。我需要使输出声明为动态的。

注意:我无法调整mycustomfunction,因为它是由Matlab编码器机器生成的代码。所以它必须是一个数组。

编辑:在这个例子中,我给了[5]一个测试用例,在这个测试用例中,我知道输出是5,但通常在运行之前我不会知道。

纯C++解决方案:使用std::vector

在C++中,对于动态数组,应该使用std::vector。它的大小可以动态地改变(例如,使用std::vector::resize(),或使用std::vector::push_back()添加元素,等等),并且std::vector知道它自己的大小(例如,调用std::vector::size())。

std::vector<double> DoSomething(...);

(注意,多亏了C++11移动语义,即使返回一个非常大的向量也是有效的。)


C-isms的解决方案

如果不能使用STL类,则可以使用原始C指针,并指定大小参数(因为原始C指针不知道所指向数组的大小)。

// The caller passes a pointer to the allocated output array, with specified size.
// The function fills the array with the result.
void DoSomething(/* some inputs ...*/, double* output, int outputSize);

还有一种选择是在函数内部分配数组,并将其作为返回值返回:

double* DoSomething( ..., int* resultSize);

或者在参数列表中使用双指针:

// Output array allocated by the function.
// The caller must free it.
void DoSomething( ..., double** output, int * resultSize);

无论如何,std::vector解决方案是最好的"纯C++"解决方案。其他的是"C主义"

正如其他人所说,创建可变长度数组的C++方法是使用std::vector。如果在调用mycustomfunction之前知道需要的数组的大小,那么您甚至可以将std::vector作为数组传递:

std::vector<double> arry;
arry.resize(5);
...
mycustomfunction(input1, input2, input3, &arry[0]);

然而,如果mycustomfunction期望realloc传递给它的指针,那么它就会失效。或者,更糟糕的是,它不会死,反而会以其他方式让你心痛。

否则,我们将需要有关mycustomfunction如何创建可变长度数组以及如何向您报告大小的更多详细信息。


有C风格的方法来处理这一问题,但它们通常依赖于这样的假设,即mycustomfunction将在内部malloc内存,而您将free内存(或者您将调用一些自定义函数来释放内存)。即便如此,mycustomfunction也需要报告它创建的元素数量,或者为您提供一些其他方法来了解它将创建多少元素。一般来说,有三种常见的方法:

mycustomfunction为您分配内存,并告诉它分配了多少内存

size_t num_elements;
double* arry = mycustomfunction(input1, input2, input3, &num_elements);
for (size_t i = 0; i < num_elements; ++i) {
    ...
}
free(arry);

我不赞成这样做,因为很容易忘记在某些代码路径中调用free

mycustomfunction为您分配内存,您必须找到一个特殊的标记(例如,非数字)才能知道它分配了多少内存

double* arry = mycustomfunction(input1, input2, input3);
for (size_t i = 0; ; ++i) {
    double d = arry[i];
    if (d != d) { // only true for not-a-number
        break;
    }
    ...
}
free(arry);

这与CCD_ 21容易泄漏的问题相同。你还需要为你的哨兵找到一个好的价值。Not-a-number(或0,或std::numeric_limits<double>::max()等)很可能是有效的输出。

在调用mycustomfunction之前分配内存,并且可以知道需要多少内存,也可以告诉mycustomfunction不要使用超出分配的内存

这是我建议的方法。它允许您使用std::vector<double>:

std::vector<double> arry;
arry.resize(how_many_will_i_need(input1, input2, input3));
mycustomfunction(input1, input2, input3, &arry[0]);
...

或者:

std::vector<double> arry;
arry.resize(HOW_MANY_I_WANT);
mycustomfunction(input1, input2, input3, &arry[0], HOW_MANY_I_WANT);
...

在C++中,std::vector(链接)可以用作具有连续内存块的容器,用于根据需要动态调整大小的数据。您可以使用模板检索数组大小并将值分配给vector:

template<typename T, size_t N>
void copy_from_array(vector<T> &target_vector, const T (&source_array)[N]) {
    target_vector.assign(source_array, source_array+N);
}

用法:

std::vector<double> vd;
double output[5];
//... initialize output
copy_from_array( vd, output);