5

I'm using gcc version 4.5.0. Using the following simple example I would assume to get an error invalid conversion from double* to const double*

#include <iostream>
using namespace std;

void foo(const double *a)
{
    cout<<a[0]*2.<<endl;
}

int main()
{
    double *a=new double[2];
    a[0]=1.;
    a[1]=2.;
    foo(a);
    return 1;
}

Why is it compiling without errors?

A counterexample is the following one which is similar:

#include<iostream>
using namespace std;

void foo(const double **a)
{
cout<<a[0][0]*2.<<endl;
}


int main()
{
    double **a=new double*[2];
    a[0]=new double[2];
    a[1]=new double[2];
    a[0][0]=1.;
    foo(a);
    cout<<a[0][0]<<endl;
    return 1;
}

(Solution for the second example: define foo as foo(const double*const* a). Thanks to Jack Edmonds comment this explains the error message)

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
pawel_winzig
  • 902
  • 9
  • 28

4 Answers4

9

Generally, you are allowed to implicitly make things "more constant" but not "less constant" in C and C++. Therefore, you are allowed to pass a non-const object to a function that takes a const object.

Basically the const parameter in the method declaration is the function's way of promising not to modify the parameter.

You can see this question for more information: Question about const_cast in c++

Community
  • 1
  • 1
Jack Edmonds
  • 31,931
  • 18
  • 65
  • 77
  • What I found strange was that I received this error message in a more complex function. Although also that function was not manipulating the array the compiler send this error, in contrast to the simple example. Therefore I was wondering which criteria the compiler is using. – pawel_winzig Oct 25 '11 at 15:30
  • prog.cpp:585:55: error: invalid conversion from ‘double***’ to ‘const double***’ prog.cpp:585:55: error: initializing argument 5 of ‘void foo(uint, scaling, uint, double, const double***, double**)’ – pawel_winzig Oct 25 '11 at 15:50
  • I was confused due to the fact, that in the following example I receive an error message: #include using namespace std; void foo(const double **a) { cout< – pawel_winzig Oct 25 '11 at 16:16
  • 1
    Ah. In that case, see http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17 Basically, change your declaration to void foo(double const* const *); – Jack Edmonds Oct 25 '11 at 16:20
6

You can pass a non-const pointer to a function that takes a const pointer. You just can't do it the other way around because that would violate constness.

Fred Larson
  • 60,987
  • 18
  • 112
  • 174
4

You have to be able to initialize a const data type. It's fine to pass a double* to a parameter that is const double*. That way you can do what you need to in the caller, but the callee is not allowed to change things you've said are const.

It's when you go the other way that you'll get errors and warnings.

i_am_jorf
  • 53,608
  • 15
  • 131
  • 222
1

The double * to const double * conversion as a parameter type is valid, as you have had many answers that tell you that.

However, there is a strange pitfall which you may have seen before that doesn't compile which might be the cause for your confusion now. If you haven't seen code similar that doesn't compile you may want to skip this answer because it might confuse you more than help. I'm only adding the extra detail in case you thought you saw this not working before.

Sometimes the const property can be violated from pasting a const type back to the CALLER via a const type parameter pointer which has less constness in the CALLER. That does cause a compile error which at first glance appears like the same kind of conversion you made. For example, if you had void bar(const double **a) function and called it with foo(&a) in your main you WOULD get a compile error even though it seems like another situation where it only appears you are making a type more constant.

See this question for more detail about that situation.

Community
  • 1
  • 1
James
  • 1,754
  • 14
  • 22