const keyword

I have been using the const keyword liberally in my code to make sure that variables are not unknowingly modified. However, i have recently ran into a problem which i had over looked before. See the code below

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

struct A{
        double *ptr;
};

void func(const A *a){
        a->ptr[0] = 1.0;
}

int main(){
        A *a; 
        a = new A;
        a->ptr = new double[10];
        a->ptr[0]=10.0;
        func(a);  
        cout<<a->ptr[0]<<endl;
        return 0;
}


func() is able to modify the contents of the variable "a" although it is declared as constant in the function argument. Is there anyway around this ? I would like to pass the pointer variable "a" to a function and also ensure that its contents are not modified ?
You have found yourself one of C++'s warts.

The const keyword is more of a compiler-assist in keeping your promise that you won't modify data.

In this particular case, you aren't modifying a... you are modifying data that it references... hence the code is perfectly legal.

The way to fix it is to make A give public access to a const double *.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
using namespace std;

struct A {
    const double* ptr() const { return m_ptr; }

    A():
        m_ptr( new double[ 10 ] )
        {
        m_ptr[ 0 ] = 10.0;
        }

private:
    double* m_ptr;
};

void func( const A* a ) {
#if 1
    a->ptr()[ 0 ] = 1.0;
#endif
}

int main() {
    A* a = new A;
    func( a );
    cout << a->ptr()[ 0 ] << endl;
    return 0;
}

As it is here, it won't compile. If you change line 18 to read #if 0 it will compile just fine. Oh, as in your example, this too is full of (memory) holes.

Hope this helps.
Thanks, this helps. So perhaps its never a good idea to have data members as public and all interactions with the data members should be done exclusively via functions which should make it easier and safer i suppose.
Not necessarily true. Value classes should probably have all members public.

A completely different solution to your problem would be to use an STL container in place of the dynamically
allocated array of doubles. Aside from fixing your problem, though, using STL containers reaps other benefits
as well: less chance of memory leaks, better exception safety.
The code i gave in my original post was the simplest version to demonstrate the issue i was looking at. This is not the actual problem. The class pointer which i pass to a function, itself has several different class pointers as members. The code is supposed to do different things based on what the user chooses. As such, I would like to create exactly the objects required and the rest would be wrapped into a single class pointer.
Here is something else i cannot explain.

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;

void func(const double **ptr){
}

int main(){
        double **ptr;
        func(ptr);
        return 0;
}


The code above doesn't compile. Why not !! I mean, all the const keyword in the function definition does is ensure that the function itself does not modify the pointer being passed as an argument. Why should the variable being passed to it also be a const ? The problem goes away if i do the following while making the function call.

 
func((const double **)ptr);


Can anyone explain why this is so ?
Here's a pretty good explanation (note const foo** is the same as foo const**):

http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17
Topic archived. No new replies allowed.