【问题标题】:c++: How to receive variable length output array from a functionc ++:如何从函数接收可变长度输出数组
【发布时间】:2014-04-15 17:41:11
【问题描述】:

我正在用 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,但通常在我运行之前我不会知道。

【问题讨论】:

  • 了解如何使用 std::vector。您可能想要使用它。
  • 但我不知道输出的大小会是多少,直到我运行这个永远不会工作的函数。所以现在你使用的是 5 号,如果你不知道应该是什么尺寸,为什么会这样呢?重写函数,例如将它拆分为一个给你大小的函数,然后是另一部分。要获得正确的答案,您应该提及 mycustomfunction 中到底发生了什么。我做了很多 matlab/C++ 接口,从来没有遇到过你遇到的问题,所以你的方法似乎有些不对劲。
  • 你自相矛盾。如果你将output 声明为一个包含 5 个元素的数组,你就知道它的大小,而且运行时不会改变它,没办法。 mycustomfunction 的签名是什么?
  • mycustomfunction(input1,input2,input3,output, size); 的大小作为参考传递以设置最大输出大小并获得结果大小
  • @MaxLybbert 不,我认为问题确实是:“我有一个函数,它需要一个指针,它应该在哪里写入它的输出。指针应该指向一些足够的可用空间函数的调用,只是我不知道这是多少。”如果是这样,答案可能是:“分配应用程序中预期的最大值(例如 1M)并祈祷,或者放弃此功能并找到其他解决方案”。

标签: c++ arrays matlab


【解决方案1】:

纯 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-isms”

【讨论】:

  • 请:int& resultSize
  • Dieter:参见例如谷歌的 C++ 风格指南。指针可以更清楚地表明函数可能会更改变量。
  • @Petter:您指的是double* DoSomething(..., int* resultSize) 案子吗?该函数可以在内部执行new[double](或malloc() 或其他),并通过返回值将指针提供给调用者。数组的大小在参数列表中指定。它有什么问题(除了我们没有使用std::vector&lt;double&gt;,这是我首先建议的,但可能与 Matlab 互操作不兼容?)?
  • @DieterLücking:是的,当然参考资料可以作为替代方案。但我开始认为 OP 需要某种形式的纯 C 接口来与 Matlab 进行一些互操作......
  • @Petter:我将纯 C++ 答案与具有更像 C 的界面的答案分开(这对于与 Matlab 等其他系统的互操作可能更好)。
【解决方案2】:

正如其他人所说,创建可变长度数组的 C++ 方法是使用std::vectorIf you know the size of the array you need before you call mycustomfunction, you can even pass a std::vector as an array:

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

但是,如果 mycustomfunction 期望 realloc 传递给它的指针,这将死。或者,更糟糕的是,它不会死,而是cause you heartache some other way

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


有 C 风格的方法来处理这个问题,但它们通常依赖于假设 mycustomfunction 将在内部 malloc 内存,而您将 free 它 (or that you will call some custom function to release the memory)。即使这样,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 为你分配内存,你必须找到一个特殊的标记(例如,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);

这和arry一样容易泄露的问题。您还需要为您的哨兵找到一个好的价值。非数字(或 0,或 std::numeric_limits&lt;double&gt;::max() 等)很可能是有效的输出。

您在调用mycustomfunction 之前分配了内存,并且有办法知道您需要多少内存,或者告诉mycustomfunction 不要使用比您分配的内存更多的内存

这是我推荐的方法。它允许你使用std::vector&lt;double&gt;:

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

【讨论】:

  • 到目前为止,这就是我能够使其工作的。但是如果输出中的实际数组大小大于 5,它会被截断,如果它更小,剩余的元素会被零填充。我不太担心充满零的情况,我可以处理它。我可以为 arry 提供一个非常大的尺寸,但不确定它可能具有的其他含义。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-01
    • 2017-06-08
    • 2014-06-17
    • 2013-06-23
    • 2021-07-11
    • 1970-01-01
    相关资源
    最近更新 更多