简体   繁体   中英

passing dynamically declared array as constant in c++

I dynamically created an array using a function like this:

//..
    double ** allocate_2d(const int wd1, const int wd2){
    double **array = new double*[wd1];

    for(int idx=0; idx<wd1; idx++)
    {
        array[idx] = new double[wd2];
    }

    return array;
}

I would like to pass the resulting array into a function as a constant parameter. I want the array to be "read only" within the function.

func(const double ** array)
{
    // computations using array
}

However I get the following error: invalid conversion from 'double**' to 'const double**'

Is it possible to do something like this?

The reason why OP's signature

func(const double ** array){
    // computations using array
}

generates an error when a double ** is passed as an argument, lies in the rules of qualification conversions.

Quoting https://en.cppreference.com/w/cpp/language/implicit_conversion (emphasis mine):

Qualification conversions

  • A prvalue of type pointer to cv-qualified type T can be converted to a prvalue pointer to a more cv-qualified same type T (in other words, constness and volatility can be added).
  • [...]

"More" cv-qualified means that

  • a pointer to unqualified type can be converted to a pointer to const;
  • [...]

For multi-level pointers, the following restrictions apply: a multilevel pointer P1 which is cv 1 0 -qualified pointer to cv 1 1 -qualified pointer to ... cv 1 n-1 -qualified pointer to cv 1 n -qualified T is convertible to a multilevel pointer P2 which is cv 2 0 -qualified pointer to cv 2 1 -qualified pointer to ... cv 2 n-1 -qualified pointer to cv 2 n -qualified T only if

  • the number of levels n is the same for both pointers;
  • if there is a const in the cv 1 k qualification at some level (other than level zero) of P1, there is a const in the same level cv 2 k of P2;
  • [...]
  • if at some level k the P2 is more cv-qualified than P1, then there must be a const at every single level (other than level zero) of P2 up until k : cv 2 1 , cv 2 2 ... cv 2 k .
  • [...]
  • level zero is addressed by the rules for non-multilevel qualification conversions.
\nchar** p = 0; \nconst char** p1 = p;  // error: level 2 more cv-qualified but level 1 is not const \nconst char* const * p2 = p;  // OK: level 2 more cv-qualified and  \n                            // const added at level 1 \n

Note that in the C programming language, const/volatile can be added to the first level only:

\nchar** p = 0; \nchar * const* p1 = p;  // OK in C and C++ \nconst char* const * p2 = p;  // error in C, OK in C++ \n

So, to enforce constness, the signature needs to be changed into

void func(double const * const * array) {
    // ...               ^^^^^ 
}

That said, I strongly suggest to change the overall design and avoid that dynamically allocated jagged array, if possible.

You can use const_cast to add constness to an object (explicit cast is needed).

double **p = allocate_2d(100,200);

// populate p

func(const_cast<const double**>(p));//array pointed by p will be read only inside func

Still, you need to consider whether you need const there at all.

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