简体   繁体   English

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

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

I am writing a wrapper in C++ which calls another C++ function. 我正在用C ++写一个包装程序,该包装程序调用了另一个C ++函数。 But the output of that function is a variable length array. 但是该函数的输出是可变长度数组。 Unfortunately, array size needs to be compile time constant. 不幸的是,数组大小需要是编译时间常数。

Current what I have: 目前我所拥有的:

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

But I don't know how much will be the size of output until I run the function. 但是在运行函数之前,我不知道输出的大小是多少。 I need to make the output declaration as dynamic. 我需要使输出声明为动态。

Note: I cannot adjust mycustomfunction as it is machine generated code by Matlab coder. 注意:我无法调整mycustomfunction,因为它是Matlab编码器由机器生成的代码。 So it has to be an array. 因此它必须是一个数组。

Edit: I gave [5] in this example for a test case where I know the output is 5, but generally I wouldn't know until I run. 编辑:在这个例子中,我给出了一个[5]的测试用例,我知道输出是5,但是通常直到运行我才知道。

The Pure C++ Solution: using std::vector 纯C ++解决方案:使用std::vector

In C++, for dynamic arrays, you should use std::vector . 在C ++中,对于动态数组,应使用std::vector Its size can be dynamically changed (eg using std::vector::resize() , or adding elements using std::vector::push_back() , etc.), and std::vector knows its own size (eg calling std::vector::size() ). 它的大小可以动态更改(例如,使用std::vector::resize()或使用std::vector::push_back()等添加元素),并且std::vector知道其自身的大小(例如调用std::vector::size() )。

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

(Note that thanks to C++11 move semantics, even returning a very big vector is efficient.) (请注意,由于使用了C ++ 11 move语义,即使返回很大的向量也是有效的。)


The solution with C-isms C-isms解决方案

If you can't use STL classes, an alternative is to use raw C pointers, and specify a size parameter (since raw C pointers don't know the size of the array pointed to). 如果您不能使用STL类,则可以选择使用原始C指针,并指定一个size参数(因为原始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);

Still another option is to allocate the array inside the function, and return it as the return value: 还有一个选择是在函数内部分配数组,并将其作为返回值返回:

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

or use a double-pointer in the parameter list: 或在参数列表中使用双指针:

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

Anyway, the std::vector solution is the best "pure C++" solution. 无论如何, std::vector解决方案是最好的“纯C ++”解决方案。 The others are kind of "C-isms" . 其他的则是种“ C主义”

In C++ std::vector ( link ) can be used as a container with contiguous memory chunk for data resized dynamically according to your needs. 在C ++中, std::vectorlink )可以用作具有连续内存块的容器,用于根据需要动态调整数据大小。 You can use a template to retrieve array size and assign values to a 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);
}

usage: 用法:

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

As others have said, the C++ way to create a variable length array is with a std::vector . 正如其他人所说,创建可变长度数组的C ++方法是使用std::vector If you know the size of the array you need before you call mycustomfunction , you can even pass a std::vector as an array : 如果在调用mycustomfunction之前知道所需的数组大小,甚至可以将std::vector作为数组传递

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

However, if mycustomfunction expects to realloc the pointer passed into it, this will die. 但是,如果mycustomfunction希望realloc传递给它的指针,这会死。 Or, worse, it won't die and will instead cause you heartache some other way . 或者,更糟糕的是,它不会死,而是会以其他方式引起您的心痛

Otherwise, we'll need additional details about how mycustomfunction creates a variable length array, and how it reports the size to you. 否则,我们将需要有关mycustomfunction如何创建可变长度数组以及如何向您报告大小的其他详细信息。


There are C-style ways to deal with this, but they generally rely on the assumption that mycustomfunction will malloc the memory internally, and you will free it ( or that you will call some custom function to release the memory ). 有C风格的方式来解决这个问题,但他们通常依赖于这一假设mycustomfunctionmalloc内部记忆,你会free它( 或者你将调用一些自定义的函数来释放内存 )。 Even then, mycustomfunction needs to either report the number of elements it created, or provide you some other way to find out how many elements it will create. 即使这样, mycustomfunction需要报告其创建的元素数量,或者提供其他方法来查找将创建的元素数量。 Broadly speaking, you have three common approaches: 广义上讲,您有三种常用方法:

mycustomfunction allocates memory for you, and tells you how much it allocated mycustomfunction为您分配内存,并告诉您分配了多少内存

size_t num_elements;
double* arry = mycustomfunction(input1, input2, input3, &num_elements);

for (size_t i = 0; i < num_elements; ++i) {
    ...
}
free(arry);

I would discourage this because it's very easy to forget to call free in some code path. 我不建议这样做,因为很容易忘记在某些代码路径中进行free调用。

mycustomfunction allocates memory for you, and you have to find a special marker (eg, not-a-number ) to know how much it allocated mycustomfunction为您分配内存,并且您必须找到一个特殊的标记(例如not-a-number )才能知道分配了多少内存

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);

This has the same problem that it's easy to leak arry . 这具有容易泄漏arry You also need to find a good value for your sentinel. 您还需要为您的哨兵找到一个好的价值。 Not-a-number (or 0, or std::numeric_limits<double>::max() , etc.) may well be a valid output. 非数字(或0,或std::numeric_limits<double>::max()等)可能是有效的输出。

you allocate the memory before calling mycustomfunction , and either have a way to know how much memory you need, or a way to tell mycustomfunction to not use more memory than you allocated 您可以在调用mycustomfunction之前分配内存,并且有一种方法可以知道所需的内存数量,或者可以告诉mycustomfunction不要使用比分配的内存更多的内存

This is the approach I would recommend. 这是我推荐的方法。 And it allows you to use a std::vector<double> : 它允许您使用std::vector<double>

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

Or: 要么:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM