4

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?

4
  • 8
    In C++ whenever you think of "dynamic array", your next thought should almost always be std::vector. Using std::vector you would not have the problem you have now (which I know there are duplicates of, even though I can't seem to find it). Commented Feb 11, 2019 at 7:04
  • Thank you. I will try that. I would still like to understand what it doesn't work. Commented Feb 11, 2019 at 7:09
  • 2
    And, in C++, if you care about performance and efficiency (which is usually why one chooses C++), whenever you think about "multi-dimensional array", your next thought should be storing its elements in a one-dimensional array ;). Commented Feb 11, 2019 at 7:10
  • 1
    See c-faq.com/ansi/constmismatch.html for why this isn't allowed. Commented Feb 11, 2019 at 11:47

2 Answers 2

4

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 cv10-qualified pointer to cv11-qualified pointer to ... cv1n-1-qualified pointer to cv1n-qualified T is convertible to a multilevel pointer P2 which is cv20-qualified pointer to cv21-qualified pointer to ... cv2n-1-qualified pointer to cv2n-qualified T only if

  • the number of levels n is the same for both pointers;
  • if there is a const in the cv1k qualification at some level (other than level zero) of P1, there is a const in the same level cv2k 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: cv21, cv22 ... cv2k.
  • [...]
  • level zero is addressed by the rules for non-multilevel qualification conversions.
 char** p = 0; const char** p1 = p; // error: level 2 more cv-qualified but level 1 is not const const char* const * p2 = p; // OK: level 2 more cv-qualified and // const added at level 1 

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

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

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.

Sign up to request clarification or add additional context in comments.

1 Comment

You should try to explain why OP's original attempt at const double ** array doesn't work.
-2

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.

7 Comments

No, the solution is to make the func definition correct.
No, people definitely don't do that. If you want to convey that a function doesn't modify a parameter, than mark the parameter as const so that the compiler prevents modification, and ensures the correct type is passed through.
@Mark Ingram, yes, that might be the right solution. People do, however, sometimes use const to let other people know that an object is not changed in the function
@Mark Ingram, I meant to say that the function doesn't modify an object, not an argument (which I corrected in my comment)
@dsp_user The const behind a method of a class is unrelated to this question.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.