将unique_ptr传递给库函数(FORTRAN函数)

3
我正在使用LAPACK库来创建一个使用C++的R包。我正在使用unique_ptr来定义数组,例如:
   unique_ptr<double[]> my_arr(new double[arr_length]);

我随后将这个unique_ptr传递给库函数(一种FORTRAN函数),该函数接受double数组的指针并将在函数中更新此数组。

   F77_CALL(daxpy) (&num_feat_, &beta, tmp, &inc_one, my_arr.get(), &inc_one);

在经过搜索后,我发现不推荐将unique_ptr作为指针参数传递给函数。然而,我正在使用的库函数需要一个指针作为它们的参数。我不能在将指针发送到函数之前释放它,因为库函数需要更新指针。有没有有效的方法来处理这个问题?

4
显然这有点让人不舒服,因为你明确地绕过了使unique_ptr安全的所有机制;但是在一个类似的问题在这里 中,共识似乎是当处理需要原始指针(Fortran,C或其他语言)的API时,只要例程不会对指针进行任何内存管理(BLAS肯定不会),使用.get()是可以接受的。请注意DAXPY不会更新指针本身;它会更新所指向的数据。 - Jonathan Dursi
@JonathanDursi 我认为这并不是一件令人感到不舒服的事情。我认为这是一件非常自然的事情。调用代码对数组拥有唯一所有权,你知道它将在调用库的过程中一直存在。我认为这是正确的调用函数的方式,即使它们在你自己的代码中。这是假设该函数没有试图获取数组的所有权并在以后调用delete的情况下,使用unique_ptr是一个坏主意。 - Chris Drew
1个回答

0

假设库不会接管数组并尝试自行delete,我认为这是完全可以的。

通常情况下,您应该优先使用引用或原始指针,并且仅在传递所有权时才传递unique_ptr,因此我认为这是正确的。调用代码保留数组的唯一所有权。

您知道数组将在函数调用后被删除,当unique_ptr超出范围时,这正是您想要的。

即使在您自己的代码中,我认为这是调用不会拥有所有权的函数的正确方法。

请参见GotW#91以获取有关如何传递(智能)指针的摘要。

如果库在函数调用后保留指针,则必须确保在库完成使用之前unique_ptr不会超出范围,这有点棘手。

有一些库假定您将在堆上分配对象,并通过原始指针拥有它们的所有权(我在某些可视化库中看到过)。他们在完成后会delete对象。这在C++11中通常被认为是不好的实践,但如果您需要调用这样的库,则不应使用unique_ptr,因为您不想自己delete对象。


为什么不将 unique_ptr 作为参数传递? 对我来说它就像Fortran的allocatable,在函数之间传递也没有问题。当函数返回时,您会得到变量的当前状态。 - Vladimir F Героям слава
@VladimirF 有些情况下,你想要传递一个 unique_ptr,最常见的是转移所有权,我已经提到了。GotW #91 给出了一个很好的总结。但在大多数情况下(比如这个例子),你不会转移所有权,应该使用原始指针或引用。除非你重新设置指针(这可能是你所指的),否则没有理由通过引用传递 unique_ptr。就我个人而言,我很少发现需要重新设置 unique_ptr,通常可以返回值来代替。 - Chris Drew

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