Question

If a function takes a const & argument it should be immutable. Why can I change values in a class passed as const? How can I prevent a function taking const & to change values? Note: compiles on vs2012 ad g++ 4.8.2

#include "iostream"

class Foo {
public:
    Foo() : a(-99) {}
    int a;
};

class Bar{
public:
    Bar (Foo& f): rFoo(f), pFoo(&f), foo(f) {}
    Foo& rFoo;
    Foo* pFoo;
    Foo  foo;
};

void setA (const Bar &  b){
    Foo* f = new Foo();
    Foo f2 = *f;
    f->a = 7;
    //b.foo.a = 8; // error C3490: 'a' cannot be modified because it is being accessed through a const object
    //b.pFoo = f;  // error C3490: 'pFoo' cannot be modified because it is being accessed through a const object
    b.pFoo->a = 9;   // OK... the pointer is const the location its pointing to not... 
    b.rFoo.a = 10;   // Maybe ... the reference may be const, the location its is referencing not ...
    b.rFoo = *f;     // Why can I modify the reference ?
}

int main(int argc, char* argv[]){
    Foo f;
    Bar b(f);

    std::cout << "one:   " << b.rFoo.a << std::endl;
    b.pFoo->a = 1;
    b.foo.a = 2;
    std::cout << "two:   " << b.rFoo.a << std::endl;
    setA(b);
    std::cout << "three: " << b.rFoo.a << std::endl;

    return 0;
}

Many Thanks in advance

Was it helpful?

Solution 2

b.rFoo = *f

is not changing rFoo itself, it is equivalent to

b.rFoo.operator=(*f);

which copies *f to the object referenced by rFoo.

OTHER TIPS

You can modify the reference for the same reason you can modify the pointed to object by pFoo. Since you aren't modifying the objects member, but another referenced object.

b.rFoo = *f; // Foo's assignment operator invoked

That's why you should not expose members variables. Since you can't enforce a prevention to modify referenced objects, other than in your own member functions.

The const qualifier of an object indicates that the abstract state of this object won't change (i.e., from the client's point of view). This is not exactly the same as saying that the object's raw bits are not going to change.

It is forbitten to C++ compilers to consider objects as raw bits, unless they can resolve the problem of aliasing. which in your case the compiler cannot. This is due to the fact that Foo* pFoo is a pointer to an object and consequently the state of this object is modifiable. That is, even if the object that pFoo points to changes, the object that contains pFoo (i.e., b) doesn't change since pFoo continues to point to the same object.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top