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.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.