将智能指针传递给函数

Posted

技术标签:

【中文标题】将智能指针传递给函数【英文标题】:Passing smart pointers to a function 【发布时间】:2015-10-30 16:42:16 【问题描述】:

我有一个二维智能指针数组。我可以给它赋值并显示它,但是我无法将它传递给一个以 double** 作为输入的函数。一个简单的 get() 不起作用。

#include <iostream>
#include <memory>
using namespace std;
# define DIM1 3
# define DIM2 4

void funcCall(double** item)

    cout<< "Test function.";


int main() 

    std::unique_ptr<std::unique_ptr<double[]>> myArray(new std::unique_ptr<double[]>[DIM1]);

    for (int i = 0; i < DIM1; i++)
    
        myArray.get()[i].reset(new double[DIM2]);
    

    std::cout<<"Assign values"<<std::endl;
    for (int i = 0; i < DIM2; i++)
    
        for (int j = 0; j < DIM1; j++)
        
            myArray.get()[j][i] = (j+1)*(i+1);
        
    

    funcCall(myArray.get());    

    return 0;

当我编译这个时,我得到:

error: cannot convert 'std::unique_ptr<std::unique_ptr<double []> >::pointer aka std::unique_ptr<double []>*' to 'double**' for argument '1' to 'void funcCall(double**)'  funcCall(myArray.get())

【问题讨论】:

在这种情况下你真的不想想嵌套unique_ptrs。 只需在调用函数时添加转换为 (double**) 即可。如果唯一的问题是编译 - 它应该可以解决您的问题 不要将#define 用于c++ 中的常量,而是首选const type name;(例如const int DIM1 = 3;)。 使用 1d 向量和索引计算 x + y * width 并将其包装在 2d 数组类中并改用它。 您将无法做到这一点。这类似于int arr[10][15] 不能作为double** 传递给函数 【参考方案1】:

调用类型和函数头不匹配。您不能将 unique_ptr 视为常规指针。

一种解决方案是将您的函数定义更改为:

void funcCall(std::unique_ptr<double[]> *item)

【讨论】:

【参考方案2】:
void funcCall(std::unique_ptr<std::unique_ptr<double[]>> & arr)

应该做你想做的,但是......

但是...

听起来您正在尝试重新发明***。不要那样做。除非这是为了任务或个人教育,否则在这种情况下会发疯。

改为使用内置容器之一。

因为DIM1DIM2是常量,所以可以使用

std::array<std::array<double, DIM2>,DIM1> myArray;

void funcCall(std::array<std::array<double, DIM2>,DIM1> arr)

但是您想要一个动态解决方案的可能性很大。在这种情况下,请尝试

std::vector<std::vector<double>> myArray(DIM1, std::vector<double>(DIM2));

void funcCall(std::vector<std::vector<double>> arr)

但是...

老实说,这是一个愚蠢的赌注。数组数组或向量向量在内存中不连续,因此计算机必须在存储中四处跳动,浪费时间在不必要的缓存未命中上,加载和可能重新加载缓存所花费的时间通常比所涉及的计算花费的时间更长。世界上所有的 133t 数学在这一点上都帮不了你,因为你已经被 IO 门控了,而 IO 是 ssssssssslllloooowwwwwwwwww。

您真正想要的是一个手动索引的漂亮一维数组。行*列数+列。当然,手动索引看起来像是额外的工作,但停下来想一想:编译器在后台做了多少数学运算才能让你的数组工作,嗯?大概差不多吧。你只是看不到它。

让我们暂时停留在 std::vector 上,但这同样适用于 std::array 甚至是一个好的 ol' 静态数组或智能指针内的动态。

std::vector<double> myArray(DIM1*DIM2);

使用这个比较简单:

myArray[row*DIM2 + column];

函数是:

void funcCall(std::vector<double> arr)

但这很容易封装在一个类中并进一步简化:

class matrix

private: 
    std::vector<double> myArray;
    size_t nrRows;
    size_t nrColumns;

public:
    matrix(size_t rows, size_t columns): 
        myArray(rows*columns), nrRows(rows), nrColumns(columns)
    

    

    double& operator()(size_t row, size_t column)
    
        return myArray[row* nrColumns + column];
    
    double operator()(size_t row, size_t column) const
    
        return myArray[row* nrColumns + column];
    
;

建筑:

matrix mat(DIM1, DIM2);

及用法:

double d = mat(1,2);

mat(2,1) = 3.14;

【讨论】:

我认为 std::array 的 std::arrays 是连续的。不是吗? static 2d Array 将是,或者至少它在 C 中。 std::array 的 std::array 应该至少接近,因为内部数组都静态分配在外部数组内,但是我不确定这是否得到保证。标准动态分配的二维数组和向量的向量,极不可能。

以上是关于将智能指针传递给函数的主要内容,如果未能解决你的问题,请参考以下文章

工厂:如何将临时智能指针传递给函数。 C++

将这个包装在智能指针中的问题传递给 C++ 中的方法

将包装在智能指针中的问题传递给C ++中的方法的问题

函数中的智能指针

智能指针总结

C++ 中带智能指针的依赖注入