1

Const functions don't seem to care if you dereference a member-pointer into a non-const reference. It's also possible to return non-const member-pointers. However it's not allowed to return a reference or an address of a data member that has a value type.

Why?

class Class
{
public:
unsigned int& value2(void) const
{
    *m_ptr = 10;
    return *m_ptr; 
    //Why?
}

unsigned int* value3(void) const
{
    return m_ptr; //Why?
}

private:
unsigned int* m_ptr;
};
NFRCR
  • 5,304
  • 6
  • 32
  • 37

5 Answers5

4

EDIT:

Regarding your code: you're never actually changing the member or returning a reference to it.

unsigned int& value2(void) const
{
    *m_ptr = 10;
    return *m_ptr; 
                //Why?
}
//returns the value your member points to, not your member

unsigned int* value3(void) const
{
    return m_ptr; //Why?
}
//returns a copy of your member

What would be disallowed would be the version I posted in my snippet.

For example:

struct A
{
   int * x;
   int& getX() const { return *x; }
   int* getX1() const { return x; }
   int*& getX2() const { return x; } //error here
};

Only the last method will return an error, because:

  • first one returns the value, which is not const. The pointer is const.
  • second one returns the pointer by value, which again is ok
  • the third one actually returns the member by reference, that's why it's illegal
Community
  • 1
  • 1
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • I'm still a newb when it comes to using const in my programs. So please correct me if I'm wrong. From what I see in your code, x is a non-const pointer to a non-const integer. However, in your point about the first function int& getX() const {return *x;}, you say that the pointer is const. If I'm right, you need to delete that part. – batbrat Aug 01 '12 at 12:44
  • @batbrat the pointer **is** const, but what it points to is not. So when you return its value `*x` you can modify it. – Luchian Grigore Aug 01 '12 at 15:48
  • I'm afraid I still don't get it. The this pointer inside getX() is constant, but x itself is declared non-const. I'd greatly appreciate it if you could clarify further. I'm also reading up on const correctness, but I find I learn better from humans with such matters. – batbrat Aug 02 '12 at 05:32
  • @batbrat the first function returns a reference to the integer that `x` points to. You're not returning `x` itself, so there's no chance of modifying it. – Luchian Grigore Aug 02 '12 at 05:46
  • Thanks for the explanation. I finally get it. Much appreciated! :) – batbrat Aug 04 '12 at 12:46
2

It does enforce the constness of the member pointers; just not the constness of what the pointers point to!

To demonstrate, the following is illegal:

class foo
{
public:
    void bar() const
    {
        p = 0;
    }

private:
    int* p;
};

Would give you a compilation error such as assignment of member 'foo::p' in read-only object.

Basically in a const member function, member variable of type T is regarded as T const, if T is a pointer type, let's say int*, this yields int* const, which means "const pointer to int", i.e. the pointer is not modifiable, but dereferencing it yields int&, not const int&. If T* was regarded as T const * or T const * const, then it'd be a different story.

As for the rationale, just because the pointer is part of the object's state, doesn't mean that the object the pointer points at is (although it can be). Changing what the pointer points at does not change the conceivable state of the object.

reko_t
  • 55,302
  • 10
  • 87
  • 77
1

I don't think I understand your question. I tried the following:

class X {
  int x;
  int* foo() const {
    return &x;
  }
};

int main() {
}

and it correctly fails to compile with a message "error: invalid conversion from ‘const int*’ to ‘int*’".

Does your problem matches the above example? If it is different, could you give an example code?


Given the more elaborate explanation of your problem now I understand you. The member pointer unsigned int* m_ptr is constant in a const-member-function. But the content that the pointer is refering to --- is not. That content is beyond the scope of your object and const functions have nothing to do with it.

Within your value2 function you won't be able to change the pointer itself. That's all.

CygnusX1
  • 20,968
  • 5
  • 65
  • 109
1

I assume this is what's bothering you.

struct Example
{
   int * p;
   Example(): i(new int) {}
   ~Example() { delete p; }
};

const Example e;
*(e.i) = 7 

This is OK, since the pointer is not changing, it still points to the same spot in memory.

However this is not OK as it changes the pointer:

e.i = new int(4);

If you want both of these to be disallowed you should instead provide an accessor function.

class Example
{
  public:
    int * i() { return i_; }
    const int * i() const { return i_; }
  protected: 
    int i_;
};

Now we have:

Example e1;
*( e.i() )=7; //OK

const Example e2;
*( e.i() )=7; // FAILS TO COMPILE.
Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
0

Const functions do respect the constness of their member variables. When you return a pointer to a function you return a pointer you return a copy of that pointer, which is okay for the same reasons you can return a copies of objects in const methods. However what the pointer is pointing to is not treated as const, so you can modify that even in a const function.

So for example:

    struct A
    {
        int n;
        int * p;
        int & f1() const {return n;} //not allowed
        int f2() const {return n;} //allowed
        int * f3() const {return p;} //allowed
        int *& f4() const {return p;} //not allowed
        int & f5() const {return *p;} //allowed, because what p points to is not const
    };
SirGuy
  • 10,660
  • 2
  • 36
  • 66