简体   繁体   中英

Passing smart pointers to a function

I have a two dimensional smart pointer array of doubles. I can assign values to it, and display it, but I am having trouble passing it to a function that takes double** as an input. A simple get() does not work.

#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;
}

When I compile this, I get:

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

The types of the call and the function header don't match. You can't treat a unique_ptr as a regular pointer.

One solution is to change your function definition to:

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

Should do what you want, but...

but...

It sounds like you are trying to reinvent the wheel. Don't do that. Unless this is for an assignment or personal education, in that case go nuts.

Instead, use one of the built-in containers.

Because DIM1 and DIM2 are constant, you can use

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

and

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

But odds are pretty good you want a dynamic solution. In that case, try

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

and

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

but...

This is a sucker bet, to be honest. An array of arrays or a vector of vectors are not contiguous in memory so the computer has to hop around in storage, wasting time on unnecessary cache misses and the time spent loading and possibly reloading cache often take longer than the computations involved. All the 133t math in the world can't help you at this point because you've become gated by IO, and IO is sssssssssslllloooowwwwwwww.

What you really want is one nice 1 dimensional array that's indexed manually. with row * number of columns + column. Sure, manual index looks like extra work, but stop and think: How much math is the compiler doing in the background to make you array work, hmmm? Probably about the same. You just don't get to see it.

Let's stuck with std::vector for now, but the same applies to std::array or even a good ol' static array or a dynamic inside a smart pointer.

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

Using this is relatively simple:

myArray[row*DIM2 + column];

The function is:

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

But this is easily wrapped in a class and simplified further:

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];
    }
};

Construction:

matrix mat(DIM1, DIM2);

and usage:

double d = mat(1,2);

or

mat(2,1) = 3.14;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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